我收到后台的回应是没有上传文件.

import ImagePicker from "expo-image-picker";
export const UpdateProfile = () => {
  const [address, setAddress] = useState("");
  const [formPostImg, setFormPostImg] = useState("");

  const [errMsg, setErrMsg] = useState<Record<string, string>>({
    profile: "",
  });

  const openImageLibraryKeyMessage = async () => {
    const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
    if (status !== "granted") {
      alert("Sorry, we need camera roll permissions to make this work!");
    }

    if (status === "granted") {
      const result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.All,
        allowsEditing: true,
      });

      if (!result.canceled) {
        setFormPostImg(result.assets[0].uri);
        console.log({ formPostImg });
      }
    }
  };

  const handleUpdateProfile = async () => {
    console.log("clicked");
    console.log({ formPostImg });

    const formBody = new FormData();
    formBody.append("address", address);
    formBody.append("img", formPostImg);
    try {
      const res = await updateProfileFn({
        formBody,
        setErrMsg,
      });
      if (res && res.message.includes("success")) {
        console.log("success");
      }
    } catch (error) {
      // disable empty object error
    }
  };

  return (
    <SafeAreaView style={styles.mainBox}>
      {errMsg.profile && <Text>{errMsg.profile}</Text>}
      <View>
        <Text>Address</Text>
        <TextInput
          onChangeText={setAddress}
          value={address}
          placeholder="Enter address"
          style={styles.textInput}
        />
      </View>

      <Pressable onPress={openImageLibraryKeyMessage}>
        <Text>Pick image</Text>
      </Pressable>

      <Pressable onPress={handleUpdateProfile}>
        <Text>Update</Text>
      </Pressable>
    </SafeAreaView>
  );
};

I console.log({ formPostImg });并获得类似于的响应

LOG  {"formPostImg": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Ffrontend-a5b88748-c8d6-412d-b8cc-ee88decfab14/ImagePicker/72bb7e65-9d16-4a78-a14e-009cd8cca53c.jpeg"}

这表明图像正在存储状态,但当我try 上传时,我从后台收到错误"No file uploaded"

这就是我要调用的函数

async function updateProfileFn({
  formBody,
  setErrMsg,
}: {
  formBody: FormData;
  setErrMsg: React.Dispatch<React.SetStateAction<Record<string, string>>>;
}): Promise<ResSuccess | undefined> {
  const url = `${BASE_URL}/api/v1/users/updateProfile`;

  const token = await SecureStore.getItemAsync("token");
  console.log({ formBody });

  const res = await fetch(url, {
    method: "PATCH",
    headers: {
      "Content-Type": "multipart/form-data",
      Accept: "application/json",
      Authorization: `Bearer ${token}`,
    },
    body: formBody,
  });

  if (!res.ok) {
    const exactErrorMsg = await res.json();
    const errorMsgString = JSON.stringify(exactErrorMsg);
    const errorMsg = JSON.parse(errorMsgString).error;

    // Set the error message in the state
    setErrMsg((prev) => ({ ...prev, profile: errorMsg }));

    // Throw an error to stop further execution
    return;
  }

  const data: ResSuccess = await res.json();

  console.log({ data });

  return data;
}
export default updateProfileFn;

这是更多上下文的后台代码

export const updateProfile: express.RequestHandler = (
  req: Request,
  res: Response
) => {
  const { id: user_id } = getUserIDAndToken(req);

  if (!user_id) {
    res.status(401).json({ error: "Unauthorized" });
    return;
  }

  upload.single("img")(req, res, async (err) => {
    if (err) {
      if (err.message === "Unexpected field") {
        // console.log(error.message);

        res.status(400).json({ error: "Maximum of 1 image allowed" });
        return;
      }
    }

    const {
      address,
      phone_number,
      account_name,
      email,
      tag,
    }: {
      address: string;
      phone_number: string;
      account_name: string;
      email: string;
      tag: string;
    } = req.body;
    console.log({ address, phone_number, account_name, email, tag });

    // create uniqueIdentifier for the image
    const uniqueIdentifier = Date.now() + "-" + Math.round(Math.random() * 1e9);

    // create publicId for the image for cloudinary
    const publicId = `profile-img-${uniqueIdentifier}`;

    console.log(req.files);
    console.log(req.file?.path);

    if (!req.file) {
      res.status(400).json({ error: "No file uploaded" });
      return;
    }

    if (!address || !phone_number || !account_name || !email) {
      res.status(400).json({ error: "Missing required fields" });
      return;
    }

    try {
      const result = await cloudinary.uploader.upload(req.file.path, {
        public_id: publicId,
      });
      const imgURL = result.secure_url;
      console.log("imgURL", imgURL);

      pool.execute<ResultSetHeader>(
        `
                UPDATE users
                SET img = ?, address = ?, phone_number = ?, account_name = ?, email = ?, tag = ?
                WHERE id = ?
                `,
        [imgURL, address, phone_number, account_name, email, tag, user_id],
        (err) => {
          if (err) {
            console.error(err);
            res.status(500).json({ error: "Internal server error" });
            return;
          } else {
            console.log({ result });
            res.status(200).json({ message: "Profile updated successfully" });
          }
        }
      );
    } catch (error) {
      console.error(error);
      res.status(500).json({ error: "Internal server error" });
    }
  });
};

这些的日志(log)

console.log(req.files);
console.log(req.file?.path);

都未定义

推荐答案

我认为您的问题可能是您的表格数据.我这样做是为了在react native中使用表单数据上传图像:

      formData.append(
        `${image.name}`,      <=== Name of upload
        {
          uri: image.uri,
          name: image.name,
          type: 'image/jpeg',
        } as any,                    <== Blob
        `${image.name}`       <=== FileName
      );

这对我有效,所以希望这也是你的问题!

React-native相关问答推荐

React Native 动画.您必须在转换属性中精确指定一个属性.

如何在react-navigation 中将drawer抽屉放在标题上?

错误发生意外错误:https://registry.yarnpkg.com/react-native-template-react-native-template-typescript:未找到

我如何知道我的代码是否作为 React Native 运行

React Redux 使用带有连接组件的 HOC

如何在react-native android中打开应用程序设置页面?

React Navigation 5 隐藏Drawer抽屉元素

Test suite无法运行 TypeError:Cannot read property ‘default’ of undefined

React native base headers for ios not found

TouchableHighlight onPress 不起作用

No such property: ABI for class: org.gradle.api.tasks.OutputFile

如何删除不需要的expo 模块

如何将 Crashlytics 与 React Native 应用程序集成

如何在不使用 JSX 的情况下在 React Native 中制作组件?

使用 React Navigation 导航堆栈时重新渲染组件

WebStorm + ReactNative?

React-native google 登录给开发人员错误

如何在 Android 手机上运行 React Native 应用程序

以编程方式读取 app.json(或 exp.json)

React Native - 为什么我需要 babel 或 webpack?