axios 为什么我的表单数据中的图像以文件大小0发送?

eyh26e7m  于 2023-10-18  发布在  iOS
关注(0)|答案(1)|浏览(127)

我可以使用Postman通过我的后端路由(到Cloudinary)上传图像,但是每次我从我的前端(Expo/RN)发送图像时,我的后端错误都会出现500错误,说文件是空的(大小:0)。
我的控制台日志中我的表单数据在前端显示非零文件大小,所以我假设我的Blob和文件正在生成,并正确地附加到表单数据。在我的后端,我收到了正确数量的文件,但问题是它们的大小都为0。
这是我的formData控制台日志:

formData [{"_data": {"__collector": [Object], "blobId": "a89556eb-d358-4fc5-846f-bb9a55292d3e", "lastModified": undefined, "name": "C6777AC5-64A4-4A03-8920-D7B2E2325345.jpg", "offset": 0, "size": 3566999, "type": "image/jpeg"}}, {"_data": {"__collector": [Object], "blobId": "6ca57385-48e8-450e-af7e-4dcd21844788", "lastModified": undefined, "name": "ABD5D206-8580-468C-9EDA-6C8D6F29F254.jpg", "offset": 0, "size": 4455509, "type": "image/jpeg"}}]

这是我的前端(Expo):

interface ImagePickerFormProps {
  page: number;
  setPage: React.Dispatch<React.SetStateAction<number>>;
  control: any;
}

export const ImagePickerForm = ({ control }: ImagePickerFormProps) => {
  const { setValue, watch } = useFormContext();
  const [status, requestPermission] = useMediaLibraryPermissions();

  const selectedAssets = watch("selectedAssets");

  const { mutateAsync } = useUploadPostMutation();

  const pickImages = async () => { // PICKED IMAGES ARE SAVED TO FORM CONTEXT
    const { status } = await requestMediaLibraryPermissionsAsync();

    if (status !== "granted") {
      await requestPermission();
    }

    const result = await launchImageLibraryAsync({
      mediaTypes: MediaTypeOptions.All,
      aspect: [16, 9],
      quality: 1,
      allowsMultipleSelection: true,
      orderedSelection: true,
      selectionLimit: 10,
      videoMaxDuration: 60,
      base64: true, // BASE64 NOT NEEDED?
    });

    if (!result.canceled) {
      setValue("selectedAssets", result.assets);
    }
  };

  const handleUploadToCloudinaryWithBlob2 = async () => {
    if (selectedAssets.length === 0) {
      console.log("selectedAssets has a length of 0");
      return;
    }

    const formData = new FormData();

    for (const asset of selectedAssets) {
      const fileNameParts = asset.uri.split(".");
      const fileExtension = fileNameParts[fileNameParts.length - 1];
      const fileName = asset.uri.split("/").pop()?.split(".")[0];
      const imageBlob = await fetch(asset.uri).then((response) =>
        response.blob()
      );
      console.log("imageBlob", imageBlob);
      console.log("imageBlob.type", imageBlob.type);
      console.log("imageBlob.size", imageBlob.size);

      const fileType = fileExtension === "jpg" ? "jpeg" : fileExtension; // HAD TO DO THIS BECAUSE BLOB TYPE CHANGED FROM JPEG TO JPG WHEN CREATING A NEW FILE... SEEMS STRANGE

      const blobFile = new File(
        [imageBlob],
        `${fileName}.${fileExtension}` || `image-${Date.now()}.${fileType}`,
        { type: `image/${fileType}` }
      );

      formData.append(`files`, blobFile, `${fileName}.${fileExtension}`);
    }

    console.log("formData", formData.getAll("files")); // SHOWS ARRAY OF IMAGES WITH NON-ZERO FILE SIZES

    try {
      const response = await axios.post(
        `${process.env.EXPO_PUBLIC_SERVER_URL}/posts/upload/cloudinary`,
        formData,
        {
          headers: {
            Accept: "application/json",
            "Content-Type": "multipart/form-data",
          },
          onUploadProgress: (progressEvent) => {
            if (progressEvent.total) {
              const progress = Math.round(
                (progressEvent.loaded * 100) / progressEvent.total
              );
              console.log(progress);
            }
          },
        }
      );

      console.log("Response:", response.data);
    } catch (error) {
      console.error("Error uploading images:", error);
    }
  };

  return (
    <Stack>
      <Stack flex={selectedAssets ? 0 : 1}>
        <Controller
          control={control}
          name="selectedAssets"
          rules={{ required: true }}
          render={() => (
            <Stack id="asset-form" flex={1} backgroundColor={"blue"}>
              <TouchableOpacity
                onPress={pickImages}
                style={{
                  justifyContent: "center",
                  alignItems: "center",
                  paddingVertical: 20,
                }}
              >
                <FontAwesome5 name="plus-circle" size={100} color="black" />
              </TouchableOpacity>
            </Stack>
          )}
        />
      </Stack>
      <Stack
        flexDirection="row"
        flexWrap="wrap"
        justifyContent="space-between"
        marginHorizontal={10}
        rowGap={20}
        flex={selectedAssets ? 0 : 1 / 2}
      >
        {renderImages()}
      </Stack>
      <Button onPress={handleUploadToCloudinaryWithBlob2}>
        Upload to cloudinary
      </Button>
    </Stack>
  );
};

我已经看了几十个问题和答案,但我仍然卡住了。我试过将图像作为base64,Blob和File发送,但每次我的后端都没有收到图像。

u59ebvdq

u59ebvdq1#

确保你使用的是Form-Data npm包。我在Expo/React Native中使用了内置的FormData模块,但由于表单类型为string,因此无法正常工作|Blob。

相关问题