Reputation: 327
After weeks trying to make this works, I wanted to ask for help before I give up.
Node endpoint is working perfectly as request from Postman sends the image and it's stored in the server. See server code below:
const multer = require('../helpers/multer');
const upload = multer(config.imagesUrl);
module.exports = function(app){
app.post('/species',
// ...
upload.single('image'),
// ...
);
But I'm not able to make this work from my React Native application. See the app code below.
import * as ImagePicker from 'expo-image-picker';
export default function AddUser({ navigation }) {
const [user, setUser] = useState(null);
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.cancelled) {
setUser({'image', result.uri});
}
};
function onSubmit(){
let formData = new FormData();
formData.append('name', user.name);
formData.append('groupId', user.group);
// Infer the type of the image
if(user.image){
let fileName = user.image.split('/').pop();
let match = /\.(\w+)$/.exec(fileName);
let fileType = match ? `image/${match[1]}` : `image`;
formData.append('image', {
uri: Platform.OS === 'android' ? user.image : user.image.replace('file://', ''),
name: user.name,
type: fileType,
});
}
axios.post(backend.url + '/user', formData, {
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data"
}
})
.then(res => {
console.log('SUCCESS');
// ...
})
.catch(err => {
console.log('ERROR');
// ...
});
}
return (
// ...
{ user.image && <Image source={{ uri: user.image }} style={{ width: 200, height: 200 }} /> }
<Button onPress={pickImage} >Pick an image</Button>
<Button onPress={onSubmit} >Send</Button>
//..
);
}
After submitting the image from the app, no errors are reported. On the server side the var req.file is undefined but see below the req.body console.log.
[Object: null prototype] {
name: 'Joe',
groupId: '5e8cdd3b8296523464c7462d',
image: '[object Object]' }
All the others application calls are running with axios and default credentials/headers are already implemented. I want to avoid to change to rn-fetch-blob or fetch.
Any idea what's missing?
Upvotes: 1
Views: 928
Reputation: 147
Sending the image as base64 in the body is bad practice. I have struggled for many hours trying to get multipart/form-data to work but it's worth it.
In your case it is likely an axios issue or an issue with how you are building and sending the fields (uri, type, name, etc). This post has more info about issues with sending images and axios
Upvotes: 0
Reputation: 327
I was not able to make it work. I found the possibility to use base64. This post explains it pretty well. I used body-parser and forgot about form-data and multer!
Upvotes: 1