我可以使用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发送,但每次我的后端都没有收到图像。
1条答案
按热度按时间u59ebvdq1#
确保你使用的是Form-Data npm包。我在Expo/React Native中使用了内置的FormData模块,但由于表单类型为string,因此无法正常工作|Blob。