我可以使用 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"}}]
这是我的前端(世博会):
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 和文件发送,但每次我的后端都没有收到图像。
确保您使用的是 Form-Data npm 包。我在 Expo/React Native 中使用内置的 FormData 模块,但它不起作用,因为表单类型是 string |斑点。