I want to send a file to the server picked using expo-document-picker OR expo-image-picker. The result object from picker is stored in providerDetails.id like this:
{"assets": [{"mimeType": "application/pdf", "name": "ID.pdf", "size": 273445, "uri": "file:///data/user/0/host.exp.exponent/cache/DocumentPicker/4eff3862-4978-4b3a-8e1a-fb0af846fe83.pdf"}], "canceled": false}
Tried "fetch" and other methods. They do not work with expo. Following code gives Parsing error, most probably by multer because it is not getting the file in request:
try {
let formData = new FormData();
formData.append("firstName", providerDetails.firstName);
formData.append("lastName", providerDetails.lastName);
formData.append("id", {
uri: providerDetails.id.assets[0].uri,
name: providerDetails.id.assets[0].fileName || providerDetails.id.assets[0].name,
type: providerDetails.id.assets[0].mimeType,
} as any );
const data = await requestProviderAccount(formData).unwrap();
} catch (error) {
console.error("Error submitting provider account request:", error);
}
Error submitting provider account request: {"data": "ENOENT: no such file or directory, open 'C:\Users\maizn\Documents\Projects\Helphive Project\Codebase\helphive-backend\uploads\1000070776.jpg'", "error": "SyntaxError: JSON Parse error: Unexpected character: E", "originalStatus": 500, "status": "PARSING_ERROR"}
Redux API Slice:
import { apiSlice } from "../../app/api/apiSlice";
export const providerApiSlice = apiSlice.injectEndpoints({
overrideExisting: true,
endpoints: (builder) => ({
requestProviderAccount: builder.mutation({
query: (formData) => {
return {
url: "provider/request-provider-account",
method: "POST",
body: formData,
};
},
}),
}),
});
export const { useRequestProviderAccountMutation } = providerApiSlice;
My server-side endpoint:
import express from "express";
import multer from "multer";
import { handleRequestProviderAccount } from "../controllers/providerController";
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./uploads");
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
const upload = multer({ storage: storage });
const providerRoute = express.Router();
providerRoute.post(
"/request-provider-account",
upload.fields([
{ name: 'id', maxCount: 1 },
{ name: 'resume', maxCount: 1 },
{ name: 'dbs', maxCount: 1 },
{ name: 'profile', maxCount: 1 }
]),
handleRequestProviderAccount
);
export default providerRoute;
Here's what I did:
I thought Content-Type: multipart/form-data was set automatically, but didn't know there was a new term also.