I am trying to upload an image retrieved with Expo's ImagePicker
. Here is my React Native component:
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>
);
};
Here is my Express backend:
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!");
}
);
When I test this in the Web version and check my Chrome console, it shows that the request was made where the photo
field is a string '[object Object]'
.
Similarly my Express endpoint parses the field as a string:
[Object: null prototype] { photo: '[object Object]' }
[object Object]
undefined
Also, another weird thing is that the photoUri
returned by ImagePicker
, at least in the Web app, defaults to the base64 encoded version instead of the actual filepath. Not sure if this is intentional:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA8Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gMTAwCv/bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA...