Javascript/React fetch api sending image via formdata - javascript

I'm trying to send a file object (image) as a multipart/form-data request using the javascript fetch api.
The code below shows how I convert the file object to string format.
The image parameter is an array of File objects. I want to send the first image of that array to a webservice.
onImageUpload = ((image) => {
//File to arraybuffer
let fr = new FileReader();
fr.onload = function(e) {
var text = e.target.result;
AccountService.uploadProfileImage(localStorage.getItem('session-key'), text)
.then((ro) => {
if(ro.code == 200) {
this.showSnackbar("Profile image uploaded successfully!");
}
else {
this.showSnackbar("Error uploading your image. Please try again later.");
}
})
}
fr.readAsText(image[0]);
})
Below is my uploadProfileImage function, which makes the post request using the fetch api.
static async uploadProfileImage(sessionKey, image) {
var reader = new FileReader();
let ro = new ResponseObject();
let fd = new FormData();
let imgObj = new Image();
imgObj.src = image;
let blob = new Blob([new Uint8Array(image)], { type: "image/jpg"});
fd.append("name", localStorage.getItem('username'));
fd.append("file", blob);
return new Promise((resolve, reject) => {
fetch(UrlConstants.BASE_URL + this.urlUploadProfileImage, {
method: "POST",
headers: {
'Authorization': 'Bearer ' + sessionKey,
"Content-type": "multipart/form-data;"
},
body: fd
}).then((response) => {
ro.code = response.status;
return response.text();
})
.then((text) => {
ro.message = text;
resolve(ro);
})
.catch((ex) => {
reject(ex);
})
});
}
When I sent the image parameter in the uploadProfileImage without converting it into a blob the data are being sent, but i need the blob to have the Content-Type: "image/jpg" in the request as the api I'm working with can't handle the request without it.
The problem that the image is not being included in the request.
How can I do that?
Thanks for your help.

Related

How to send text and formData in one fetch call

I am trying to send text and formData in one fetch call to a Node.js backend using multer.
I can send formData on its own with no issues, but when I try and add text, the api call stays 'pending'.
Here is my fetch call that works just with formData:
const handleImage = async (e) => {
var formData = new FormData();
let file = e.target.files[0];
formData.append("image", file);
try {
const upload = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_API}/uploadImage`,
{
method: "POST",
body: formData,
}
);
} catch (e) {
console.log("Something went wrong!");
}
};
Here is the same fetch call with text added that does not work:
const handleImage = async (e) => {
var formData = new FormData();
let file = e.target.files[0];
formData.append("image", file);
try {
const upload = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_API}/uploadImage`,
{
method: "POST",
body: {formData, userId}
}
);
} catch (e) {
console.log("Something went wrong!");
}
};
It also doesn't work if I try and user JSON.stringify().
I do believe that you can't send a formData and json body at the same time (maybe there is a way somehow i don't know)
because multer will just take the file from formdata and the other property will be set to req.body so if you want to send userId you can try
const handleImage = async (e) => {
var formData = new FormData();
let file = e.target.files[0];
formData.append("image", file);
formData.append("userId", userId);
try {
const upload = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_API}/uploadImage`,
{
method: "POST",
body: formData,
}
);
} catch (e) {
console.log("Something went wrong!");
}
};

request in node works but in js (vue) doesnt

Hi I have a backend which receive a request with a picture and storage, I try it with postman and with the code below and works perfectly
var axios = require('axios')
var FormData = require('form-data')
var fs = require('fs')
var data = new FormData()
data.append('file', fs.createReadStream('index.png'))
console.log('HEADERS')
console.log(data.getHeaders())
let config = {
method: 'post',
url: 'http://localhost:5013/v1/business/honda/widget/test/',
headers: {
...data.getHeaders(),
},
data: data,
}
The problem is in my vue app I try to do it with the next code, I have 2 buttons with one load the image and the other to send it.
In the back end I have the follow error when try to pick 'file'
http: no such file
let imageData
//send the image to backend
function funtest() {
console.log('image')
const formData = new FormData()
const url = 'http://localhost:5013/v1/business/honda/widget/test/'
formData.append('file', imageData)
let config = {
method: 'post',
url: url,
headers: {
'Content-type': 'multipart/form-data',
},
data: formData,
}
axios(config)
.then((response) => {
console.log('RESPONSE')
console.log(response)
})
.catch((error) => {
console.log('ERROR')
console.log(error)
})
}
//function to read the image
function onImage(data) {
const reader = new FileReader()
reader.onload = (e) => {
imageData = e.target.result
console.log('imagen')
}
reader.readAsDataURL(data.target.files[0])
}
I think it's probably not reading the path to index.png file correctly here, fs.createReadStream('index.png')
Consider using path like this
const path = require('path');
const filePath = path.join(__dirname, 'index.png');
data.append('file', fs.createReadStream(filePath))
NB: This is just a quick and dirty suggestion, and it's not guaranteed to work but it's definitely worth a shot

Vuejs won't send correct data

I have image field, when I change the image it does change the image and before I send it to back-end I can see the values are correct, but sent data values are empty!
Code
Commented
save_changes() {
/* eslint-disable */
if (!this.validateForm) return;
console.log("image: ", this.data_local.image); // new image data are present
this.$http
.put(
"/api/admin/posts/meta/" + this.$route.params.id,
this.data_local, // new image data is empty!
{
headers: {
Authorization: localStorage.getItem("access_token"),
},
}
)
.then((res) => {
}
//rest of it...
},
update_avatar(event) {
this.dialogVisible = true;
this.dialogImageUrl = URL.createObjectURL(event.target.files[0]);
this.data_local.image = event.target.files[0]; // this is where I sent selected image and pass it to my `data_local` array objects
},
Screenshots
Any suggestions?
Update
header request
What you can try is to send it as an FormData
let file = this.data_local.image
let image = URL.createObjectURL(file)
let formData = new FormData();
formData.append("image", image);
formData.append("id", 71);
formData.append(....)
this.$http
.put(
"/api/admin/posts/meta/" + this.$route.params.id,
formData,
{
headers: {
Authorization: localStorage.getItem("access_token"),
},
}
)
.then((res) => {
}
The headers should look something like this:
Your image should have this (binary)

how to resolve axios post request 413 payload too large?

Iam getting the error 'axios post request 413 payload too large' when trying to upload images/screenshots of size (700~) kb.I am able to upload small files though.Iam trying do a post operation to upload this file into the blob table in my postgres database.
upload functionality
function readFileAsync(file) {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
var base64String = reader.result;
console.log(base64String)
console.log(base64String.substr(base64String.indexOf(',') + 1))
resolve(base64String.substr(base64String.indexOf(',') + 1));
};
reader.onerror = reject;
reader.readAsDataURL(file);
})
}
async function uploadFile(path, data) {
try {
let contentBuffer = await readFileAsync(data.chosenfile);
console.log('content buffer is'+contentBuffer)
let response = await axios({
method: 'post',
url: 'api/store/blob' + path,
headers: {'session_id': data.sessionid},
data: {"id":data.chosenfile.name, "file": contentBuffer }
});
if (response.status == 200) {
console.log(response.status);
}
return response.data;
} catch (err) {
console.error(err);
}
}
As you can see from the code i am converting the file to base64url and from the url i am sending out only the base64 string in the axios payload. Plz help ?

How to send data in api without losing it

Below code i'm adding objects to media array in reactJS
const formData = new FormData()
formData.append('file', file, file.name)
const obj = {
'id': id,
'type': 'doc',
'data': formData,
url: file
};
setID(id + 1);
setMedia([...media, obj]);
Now i send it to api via axios
function addNew() {
setProgressing(true)
axios.post(uri + '/api/add', {
map_id: props.data.id,
questions: JSON.stringify(media)
})
.then(res => {
props.updateStep();
})
.catch(err => {
});
}
But on server end i receive object of array like below
see data and url is empty
{id: 1, type: "image", data: {{}}, url: {}}
this is request header
SetMedia code which call on each image upload
function handleUploadChange(e) {
handleClose();
const file = e.target.files[0];
if (!file) {
return;
}
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = () => {
const formData = new FormData()
formData.append('file', file, file.name)
const obj = { 'id': id, 'type': 'image', 'data': formData, url: file };
setID(id+1);
setMedia([...media, obj]);
}
reader.onerror = function () {
console.log("error on load image");
};
}
i find solution for it.
i convert images in base64 and send string in request and on server side convert it again to images.

Categories

Resources