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
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!");
}
};
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
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)
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 ?
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.