The react native app (Android in this case) is supposed to upload files selected using the react-native-document-picker and POST it to the backend api. The backend is a Spring Boot app and uses Apache Commons Fileupload and therefore multipart=false. Now in Angular, I am able to append the files to a formData, which would be passed in the request body where as other "@RequestParams" would be sent via HttpParams.
I tried the similar approach but didn't work, not sure what I am missing. The following solutions also didn't help:
- File upload in React Native through fetch, XHR and axios fails on Android but works on iOS
- How to Send the document from react native DocumentPicker response to a web api as byte[]
Note: I cannot modify the backend api to enable multipart. Axio is used for api calls
This is what I have right now:
UploadButton import { uploadDocuments } from '../../services/ApiService';
const result = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles]
});
const uploadData = {
parentId: 1,
userId: 1
}
const data = new FormData();
data.append("file", files[0]);
uploadFiles(data, uploadData).then(res => {
console.log('files uploaded');
}).catch((err) => {
console.log('errr uploading files: ' + JSON.stringify(err));
})
uploadFiles - API Service
return axios.post(`${API_URL}/api/uploadFiles`, formData, {
params: {
parentId: parentId,
userId: userId
},
responseType: 'text',
headers: { 'Content-Type': 'multipart/form-data' }
});
Spring Boot API
@PostMapping(value = "/uploadFiles", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
public ResponseEntity<String> addDocuments(@RequestParam Long parentId,
@RequestParam Long userId,
HttpServletRequest request) {
//
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(UPLOAD_DIR));
factory.setSizeThreshold(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
factory.setFileCleaningTracker(null);
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
// rest of the code
}
Logs - All I get is 400 Bad Request - No errors in backend
LOG uploading files: 1
LOG file data => name: sample.pdf uri: content://com.android.externalstorage.documents/document/primary%3Asample.pdf
LOG dots: [{"guid":"170560870473535714196193642705","displayName":"sample.pdf"}]
LOG errr uploading files: {"message":"Request failed with status code 400","name":"AxiosError","stack":"AxiosError: Request failed with status code 400\n at settle (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.dvsapp&modulesOnly=false&runModule=true:174577:37)\n at onloadend (http://10.0.2.2:8081/index.bundle//&platform=android&dev=true&lazy=true&minify=false&app=com.dv***Trimmed to clear spam filter***,"config":{"transitional":{"silentJSONParsing":true,"forcedJSONParsing":true,"clarifyTimeoutError":false},"adapter":["xhr","http"],"transformResponse":[null],"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"maxBodyLength":-1,"env":{},"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"multipart/form-data","Authorization":"Bearer eyJhbGciOiJ},"params":{"parentId":2,"userId":22,"responseType":"text","method":"post","url":"https://apigone.virtual-datarooms.uk/api/buploadFiles","data":{"_parts":[["file",{"fileCopyUri":null,"size":861148,"name":"sample.pdf","type":"application/pdf","uri":"content://com.android.externalstorage.documents/document/primary%3Asample.pdf"}]]}},"code":"ERR_BAD_REQUEST","status":400}