使用 Expo 时作为字符串“[object Object]”上传的图像的表单数据
Form data of image uploaded as string '[object Object]' when using Expo
我正在尝试上传使用 Expo ImagePicker
检索到的图像。这是我的 React Native 组件:
import * as ImagePicker from "expo-image-picker";
const Foo = () => {
const [photoUri, setPhotoUri] = useState("");
const choosePhoto = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
quality: 1,
});
setPhotoUri(result.cancelled ? "" : result.uri);
};
const uploadPhoto = async () => {
if (photoUri == "") {
return;
}
const formData = new FormData();
formData.append("photo", {
uri: photoUri,
name: "test",
type: "image/jpeg",
});
return await fetch(Constants.manifest.extra.UPLOAD_IMAGE_URI, {
method: "POST",
body: formData,
headers: {
// No header otherwise multer will complain about missing boundary
// "content-type": "multipart/form-data",
},
});
};
return (
<View>
<TouchableOpacity onPress={choosePhoto}>
<Text>Choose Photo</Text>
<TouchableOpacity onPress={uploadPhoto}>
<Text>Confirm Image</Text>
</TouchableOpacity>
</TouchableOpacity>
);
};
这是我的 Express 后端:
import * as express from "express";
import * as multer from "multer";
const app = express();
const fileUpload = multer();
app.post(
"/profile_image/upload",
fileUpload.single("photo"),
async (req, _res, _next) => {
console.log(req.body);
console.log(req.body.photo);
console.log(req.file);
}
);
app.listen(
{
port: 8000,
},
() => {
console.log("Started server!");
}
);
当我在 Web 版本中测试它并检查我的 Chrome 控制台时,它显示请求是在 photo
字段是字符串 '[object Object]'
.[=19 的地方发出的=]
同样,我的 Express 端点将字段解析为字符串:
[Object: null prototype] { photo: '[object Object]' }
[object Object]
undefined
此外,另一个奇怪的事情是 ImagePicker
返回的 photoUri
,至少在 Web 应用程序中,默认为 base64 编码版本而不是实际文件路径。不确定这是否是故意的:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA8Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gMTAwCv/bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA...
请注意,当 uri
不是 base64(例如,在 Android/iOS 上)时,需要具有 uri, type, name
键的字段对象,但需要以下内容才能使用 ImagePicker
在网络上,因为它 returns 一个 base64
编码。
选项 1:base64 字段
所以我意识到,因为我正在上传图像的 base64 编码,所以我不需要将 photo
字段包装在字典中,而是可以这样做:
formData.append("photo", photoUri);
此外,由于 photoUri
是 O(1MB),我需要将 multer
的字段大小限制增加到合理的值(在本例中为 5MB):
const fileUpload = multer({
limits: { fieldSize: 5 * 1024 * 1024 * 1024 },
});
随后我能够在 req.body.photo
中检索图像的 base64 编码。
选项 2:blob 编码
另一个选项是 convert the base64 encoding to a Blob,因此它适用于 FormData。
formData.append("photo", dataURItoBlob(photoUri));
然后 multer 将能够将以上内容解析为没有任何限制覆盖的文件:
app.post(
"/profile_image/upload",
fileUpload.single("photo"),
async (req, _res) => {
console.log("file", req.file);
}
);
file {
fieldname: 'photo',
originalname: 'blob',
encoding: '7bit',
mimetype: 'image/jpeg',
buffer: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff fe 00 3c 43 52 45 41 54 4f 52 3a 20 67 64 2d 6a 70 65 67 20 76 31 2e 30 20 28 75 73 69 ... 2332888 more bytes>,
size: 2332938
}
我正在尝试上传使用 Expo ImagePicker
检索到的图像。这是我的 React Native 组件:
import * as ImagePicker from "expo-image-picker";
const Foo = () => {
const [photoUri, setPhotoUri] = useState("");
const choosePhoto = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
quality: 1,
});
setPhotoUri(result.cancelled ? "" : result.uri);
};
const uploadPhoto = async () => {
if (photoUri == "") {
return;
}
const formData = new FormData();
formData.append("photo", {
uri: photoUri,
name: "test",
type: "image/jpeg",
});
return await fetch(Constants.manifest.extra.UPLOAD_IMAGE_URI, {
method: "POST",
body: formData,
headers: {
// No header otherwise multer will complain about missing boundary
// "content-type": "multipart/form-data",
},
});
};
return (
<View>
<TouchableOpacity onPress={choosePhoto}>
<Text>Choose Photo</Text>
<TouchableOpacity onPress={uploadPhoto}>
<Text>Confirm Image</Text>
</TouchableOpacity>
</TouchableOpacity>
);
};
这是我的 Express 后端:
import * as express from "express";
import * as multer from "multer";
const app = express();
const fileUpload = multer();
app.post(
"/profile_image/upload",
fileUpload.single("photo"),
async (req, _res, _next) => {
console.log(req.body);
console.log(req.body.photo);
console.log(req.file);
}
);
app.listen(
{
port: 8000,
},
() => {
console.log("Started server!");
}
);
当我在 Web 版本中测试它并检查我的 Chrome 控制台时,它显示请求是在 photo
字段是字符串 '[object Object]'
.[=19 的地方发出的=]
同样,我的 Express 端点将字段解析为字符串:
[Object: null prototype] { photo: '[object Object]' }
[object Object]
undefined
此外,另一个奇怪的事情是 ImagePicker
返回的 photoUri
,至少在 Web 应用程序中,默认为 base64 编码版本而不是实际文件路径。不确定这是否是故意的:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA8Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gMTAwCv/bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA...
请注意,当 uri
不是 base64(例如,在 Android/iOS 上)时,需要具有 uri, type, name
键的字段对象,但需要以下内容才能使用 ImagePicker
在网络上,因为它 returns 一个 base64
编码。
选项 1:base64 字段
所以我意识到,因为我正在上传图像的 base64 编码,所以我不需要将 photo
字段包装在字典中,而是可以这样做:
formData.append("photo", photoUri);
此外,由于 photoUri
是 O(1MB),我需要将 multer
的字段大小限制增加到合理的值(在本例中为 5MB):
const fileUpload = multer({
limits: { fieldSize: 5 * 1024 * 1024 * 1024 },
});
随后我能够在 req.body.photo
中检索图像的 base64 编码。
选项 2:blob 编码
另一个选项是 convert the base64 encoding to a Blob,因此它适用于 FormData。
formData.append("photo", dataURItoBlob(photoUri));
然后 multer 将能够将以上内容解析为没有任何限制覆盖的文件:
app.post(
"/profile_image/upload",
fileUpload.single("photo"),
async (req, _res) => {
console.log("file", req.file);
}
);
file {
fieldname: 'photo',
originalname: 'blob',
encoding: '7bit',
mimetype: 'image/jpeg',
buffer: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff fe 00 3c 43 52 45 41 54 4f 52 3a 20 67 64 2d 6a 70 65 67 20 76 31 2e 30 20 28 75 73 69 ... 2332888 more bytes>,
size: 2332938
}