How to send a file from ReactJs to Flask using Axios - reactjs

I am attempting to send a file from a ReactJs Frontend, using an axios call, to a flask Backend.
Here is my axios call:
const audio_file = new File(buffer, 'recording.mp3', {
type: blob.type,
lastModified: Date.now()
});
const blobURL = URL.createObjectURL(blob);
this.setState({blobURL, isRecording: false, recorded:true})
let options = {
method: 'POST',
url: flaskEndpoint + "audio/1",
file: audio_file,
crossOrigin:'*'
}
console.log(options)
axios(options)
.then(response => {
console.log(response)
})
.catch(error => {
console.log("Error in the axios call:" + error);
})
At the moment my flask method looks like this :
#app.route('/audio/<int:user_id>', methods=['POST'])
#cross_origin()
def make_audio(user_id):
print(request.files.get('recording.mp3'))
print(request.files)
return 0
Here is the console of the python app:
And here is the web console of the React App:
Am I making a mistake here?
Edit
Ok I tried the suggestion of converting the file to base64 and then sending the file the backend.
This is my new axios call.
let options = {
method: 'POST',
url: flaskEndpoint + "audio/1",
data: convertBlobToBase64(blob),
// file: audio_file,
crossOrigin:'*',
headers: {
'Content-Type': 'application/json'
},
json: true
}
console.log(options)
axios(options)
.then(response => {
console.log(response)
})
.catch(error => {
console.log("Error in the axios call:" + error);
})
});
Here is the convetBlobtoBase64 functions (borrowed from: https://gist.github.com/n1ru4l/dc99062577b746e0783410b1298ab897)
const convertBlobToBase64 = blob => new Promise((resolve, reject) => {
const reader = new FileReader;
reader.onerror = reject;
reader.onload = () => {
resolve(reader.result);
};
reader.readAsDataURL(blob);
});
And here is what is being sent to the backend:
I think this answers my question, although I will create another to work out how to access the data on the flask end.

Related

Parsing fetched XML with react-xml-parser

I am first fetching xml data from an external api in my backend and then trying to send that to the frontend.
Backend (server):
app.get("/api", (req, res) => {
var request = require('request');
var options = {
'method': 'GET',
'url': 'http://link',
'headers': {
}
};
request(options, function (error, response) {
console.log("TEST1")
console.log(response.body)
if (error){
console.log("TEST2")
res.status(404).write("NO LUCK");
}
console.log("TEST3")
res.status(200).write(response.body);
});
});
The xml appears in my terminal correctly. TEST1 and TEST2 do too.
Frontend (client):
import XMLParser from 'react-xml-parser';
useEffect(() => {
fetch("/api")
.then(res => res.text())
.then(data => {
var xml = new XMLParser().parseFromString(data);
console.log(xml)
})
.catch(err => console.log(err));
}, []);
Nothing appears on the console. I got the frontend code from this stack overflow post.
fetch("/api")
.then((res) => res.body)
.then((data) => console.log(data));
If I log the response body like this I get a ReadableStream object. This is the only functionality I've been implementing so far so nothing should be interfering with it. When I try different approaches I keep needing to restart React or it will load endlessly when I refresh.
When I open http://localhost:3001/api I can see the xml data I'm trying to transfer.
Still not sure why it didn't work before but it works with this.
Frontend (client):
import axios from "axios";
axios.get('/api')
.then(xml => {
console.log(xml.data);
})
Backend (server):
app.get('/api', (req, res) => {
var axios = require('axios');
var config = {
method: 'get',
url: 'http://link',
headers: {'Content-Type': 'application/xml'}
};
axios(config)
.then(function (response) {
res.json(response.data);
})
.catch(function (error) {
console.log(error);
})
})

How to send body with formData inside as a key fetch api

When I try to send image and a path to Api, it sends like [object Object]
export async function uploadImageToCDN(image: FormData, directory: string = 'dir'): Promise<any> {
const token = await authoriseInApi()
const headers = []
headers.push(['Authorization', `Bearer ${token}`])
const data: Content = new Content('multipart-file', {
file: image,
dir: directory
})
return post<any>('https://test-api.test.com/files/upload', data, headers)
}
This is how I collect data and send to Api:
const formData = new FormData()
const imageBase64 = await getBase64(file)
const imageUri = dataURIToBlob(imageBase64)
formData.append('image', imageUri)
const res = uploadImageToCDN(formData)
What is a mistake?
You need to use JSON.stringify(data) to send object parameter:
return post<any>('https://test-api.test.com/files/upload', JSON.stringify(data), headers)
Or if you want to use fectch try same thing:
//POST request with body equal on data in JSON format
fetch('https://example.com/profile', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
I wrote xhr request and everything work fine.
Here is my request:
export async function uploadImageToCDN(formData: FormData): Promise<ICDNUploadResponse> {
return new Promise(async (resolve, reject) => {
const token = await getApiTokenByScope('scope')
const xhr = new XMLHttpRequest()
xhr.open('post', '/api/test/files/upload')
xhr.responseType = 'json'
xhr.setRequestHeader('Authorization', `Bearer ${token}`)
xhr.onload = async () => {
if (xhr.status === 401) {
await refreshApiTokenByScope('scope')
.then(() => {
uploadImageToCDN(formData)
})
}
resolve(xhr.response)
}
xhr.onerror = () => {
reject(xhr.response)
}
xhr.send(formData)
})
}

What link do I call to Amazon s3 when I use axios

I'm new to S3 so I didn't find anywhere in the API where it says that this is the respective URL to use for the axios URL parameter. I'm keeping on getting a 404 error saying that the
axios({
url: `call/s3/backend`,
method: "post",
data: {
//images: imageArray.toByteArray(),
},
})
.then((res) => {
//imageUrlArr = res.data;
axios({
url: `api/petition_posts`,
method: "post",
data: {
petition_post: {
title: title,
description: description,
hashtags: arrayOfHashtags.join(" "),
amount_donated: 0,
//media: imageUrlArr,
goal: money,
card_type: "petition",
org_profile_id: 1,
},
},
})
.then((res) => {
console.log(res.data);
})
.catch((error) => console.log(error));
})
.catch((error) => console.log(error));
}
titleError(true ? title.length === 0 : false);
descriptionError(true ? description.length === 0 : false);
};
To upload a file from the browser to S3 using Axios:
fetch a pre-signed S3 URL from your server
PUT the file to the pre-signed URL using Axios
Server:
const aws = require('aws-sdk')
aws.config.update({
accessKeyId: '...',
secretAccessKey: '...'
})
const s3 = new aws.S3()
const params = {
Bucket: 'my-bucket',
Key: 'my-file.txt',
Expires: 300,
ContentType: 'text/plain'
}
s3.getSignedUrl('putObject', params,
(error, signedUrl) => return signedUrl /* to client */ )
Client:
const axios = require('axios')
axios.put(<signed-url-from-server>, 'abc', {
headers: {
'Content-Type': 'text/plain'
}
}).then(res => console.info(res))
.catch(err => console.error(err))

How to upload image to API in React Native via FormData

I am available to upload image to server via postman:
Here is a picture of my postman config.
Postman Config
I am using Axios and here is my config:
uploadPhoto = () => {
let formdata = new FormData();
let i = {
uri: this.state.profilePhoto.uri,
type: "multipart/form-data",
name: `image.jpg`,
};
formdata.append("user[image]", i);
console.log("This is formdata", formdata);
Axios.put(EDIT_PROFILE_API, {
headers: {
"Content-Type": "multipart/form-data",
apisecret: this.props.api_secret,
},
body: formdata,
})
.then((response) => {
response.text().then((res) => {
console.log(res);
});
})
.catch((error) => {
console.log(error, "Image is not uploaded");
});
};
It gives me an error when i try upload it to server. What i am doing wrong?
I am getting this error message: enter image description here

Sending Multipart file and #RequestBody in single request

In the React web app I'm developing,there is a file upload part with some user data.However, when I'm trying to upload files, server throws the following error.
org.apache.tomcat.util.http.fileupload.FileUploadException: the
request was rejected because no multipart boundary was found
React side
function fileChangedHandler(event) {
let formData = new FormData();
formData.append("file", event.target.files[0]);
formData.append("name", event.target.files[0].name);
SENDER.post(
"/api/task_resources",{
addedBy: parseInt(localStorage.getItem('id')),
taskId: parseInt(props.taskId)
},{
params: {
file: formData
}
}
)
.then(res => {
if (res.status === 200) {
alert("upload suc");
window.location.reload()
}
})
.catch(err => alert("err"));
}
My Spring Boot controller is as follows.
#PostMapping("/task_resources")
public void addResourceToTask(#RequestParam("file") MultipartFile file,#RequestBody AddTaskResourceRequest addResReq) {
String fileName = fileService.storeFile(file);
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/api/downloadFile/")
.path(fileName)
.toUriString();
UploadFileResponse response = new UploadFileResponse(fileName, fileDownloadUri,
file.getContentType(), file.getSize());
taskResourceService.addResource(addResReq, fileDownloadUri);
}
You need to send the request using multipart/form-data if your server is especting that. Here is my example implemented using Axios.
const postGalleryImageRequest = async (sessionToken, userLogged, image) => {
const data = new FormData();
data.append('newImage', image);
const result = await api.post('business/' + userLogged.businessId + '/gallery', data, {
headers: {
Authorization: sessionToken,
'Content-Type': 'multipart/form-data',
}
}) .then((response) => {
return response.data
})
.catch(error => {
....
})
return result;
}

Resources