API doesn't receive file + text posted through a FormData - javascript

I want to upload an file with a text to my api. The Api says that the schema is not JSON but multipart. So I included the information(image and text) in a FormData in order to post it to the api afterwards.
This looks like this:
My class model:
export class FormData {
image: any;
category: string;
constructor(args){
this.image = args.image;
this.category = args.category;
}
}
api call:
apiSubmit() {
const formData = new FormData(this.categoryForm.value);
console.log(formData);
this.http.post<any>(this.url, formData, httpOptions).subscribe(
(res) => console.log(res),
);
}
The values are actually assigned to formData, so FormData has both values the file and the text stored.
But somehow the data doesn't find its was to the api properly:( when I want to post, the api spits out the following error.
Do I somehow have to singely show the api which part of the FormData is the file and which part is the string? And if yes how would I do that?

this maybe work. You must send a Blob type.
In this example I'll send a base64 file, this is a better option.
export class FileData {
contentBase64: string;
mimeType: string;
name: string;
}
apiSubmit() {
const formData = new FormData();
const blob = new Blob([file.contentBase64], { type: file.mimeType });
formData.append('file', blob, file.name);
this.http.post<any>(this.url, formData, httpOptions).subscribe(
(res) => console.log(res),
);
}

Related

multipart/form-data not being automatically set with axios in React Native

When attempting to upload a file to Amazon S3 using axios, I have been encountering a very strange issue. Normally, in a web browser, when FormData has binary data in it, the Content-Type header automatically gets set to multipart/form-data; boundary=<some random string>. However, I have been completely unable to achieve that in React Native (testing on an iOS device). The Content-Type is automatically set to application/json, and thus not being detected as a correctly formatted body when uploading to Amazon S3. I have tried specifying a blob in the file parameter in FormData instead of the URI to the file as well to no avail. I have appended my code below, any advice would be very much appreciated.
const uploadFileToS3 = (
presignedPostData,
file) => {
// create a form obj
const formData = new FormData();
// append the fields in presignedPostData in formData
Object.keys(presignedPostData.fields).forEach(
key => {
formData.append(
key,
presignedPostData.fields[key],
);
},
);
// append the file and uplaod
const getBlob = async () => {
const img_url = previewPath;
let result = await fetch(img_url);
const blob = await result.blob();
formData.append('Content-Type', 'image/jpeg');
formData.append('file', {
uri: previewPath,
type: 'image/jpeg',
name: 'test.jpeg',
});
console.log(formData, 'wild');
// post the data on the s3 url
axios
.post(presignedPostData.url, formData)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error.response);
});
};
getBlob();
};

How to send binary file multipart/form-data using post Angular?

I have tried to send a binary file with additional fields using post method and multipart/form-data.
load() {
const formData = new FormData();
formData.append('file', this.data.binary);
formData.append('reasons', this.form.get('reasons').value);
const headers = new HttpHeaders({
key: userKey,
});
const options = { headers: headers };
this.http
.post(`/api/Controller`, formData, options)
.pipe(catchError(this.handleError))
.subscribe(
() => {
alert('Success');
},
(error) => {
alert(error.Message || 'Error');
},
);
}
Where this.data.binary is:
try {
const input = event.target as HTMLInputElement;
const reader = new FileReader();
reader.onload = () => {
this.data.binary = reader.result;
};
reader.readAsArrayBuffer(input.files[0]);
} catch (e) {
alert(e);
}
In Chrome headers I see this data after submit:
FormData
file: [object ArrayBuffer]
reasons: text
How to send file as binary correct?
I have trird also this:
formData.append('file', new Blob(this.data.binary));
don't use the FileReader to read it as binary.
Just use the FormData and append it directly
const formData = new FormData()
formData.append('file', input.files[0])
beside, readAsBinaryString is a bad practices and should use arrayBuffer instead when dealing with binary
I would also suggest that you do something like new FormData(formElement) so that you don't have to append/set every single field that is needed.

Formdata is blank at the backend

I pass image data by appending with formdata in reactjs
This is the handler for this
handleUserImage(e) {
const input = e.target
if (input.files && input.files[0]) {
const reader = new FileReader()
reader.onload = (r) => {
const formdata = new FormData()
formdata.append('photos', input.files[0])
formdata.append('fileName', input.files[0].name)
this.props.uploadImage({ image: formdata })
}
reader.readAsDataURL(input.files[0])
}
}
and when I console it to backend it looks like blank object
{ image: {} }
Then how can I pass formdata and upload the image
Edit : Upload image api call
export const uploadImage = (data) => {
console.log(data)
return fetch(`http://hostName:3001/town/image`, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data'
},
body: data
})
.then((res) => {
return res.json()
})
.then((payload) => {
console.log(payload)
return payload
}).catch((error) => {
throw error
})
}
when I console it to backend it looks like blank object
This is normal.
headers: {
'Content-Type': 'multipart/form-data'
},
Multipart form data MIME types need to have a parameter to describe the boundary marker (so parsers know where one field ends and the next begins).
Yours is missing it. What's more, there is no way for you to know what it will be.
Don't override the Content-Type header, allow fetch to generate it from the FormData object. Remove the code I quoted entirely.
Why use FileReader, upload it as base64 and append file name separately?
you can just do
handleUserImage (evt) {
const file = evt.target.files[0]
if (file) {
const formdata = new FormData()
formdata.append('photos', file)
this.props.uploadImage({ image: formdata })
}
}
You save a few bytes,
avoid unnecessary decode & encode calculations
runs faster
saves ~3x bandwidth
FormData.append(name, value, filename)
name
The name of the field whose data is contained in value.
value
The field's value. This can be a USVString or Blob (including subclasses such as File).
filename Optional
The filename reported to the server (a USVString), when a Blob or File is passed as the second parameter. The default filename for Blob objects is "blob". The default filename for File objects is the file's filename.
-- MDN - FormData.append()

why I use fetch to upload img in react don't have fileName?

I use fetch to upload images in react,my code is like below:
let formData = new FormData();
let file = {uri: imgdata, type: 'multipart/form-data', name: '2_resources.jpg'};
formData.append("name", "name");
formData.append("mobile", "18381307123");
formData.append("content", "123654");
formData.append("resources", file,"2_resources.jpg");//mind this line
fetch(Config.report,
{
mode: 'cors',
method: "POST",
body: formData
})
.then(res => res.json())
.then((data) => {
console.log(data)
}
).catch((err) => {
console.log(err)
}
);
but,run it I get the request :
I have look for FormData API document on https://developer.mozilla.org/en-US/docs/Web/API/FormData
it have write below:
and the fetch used is :"isomorphic-fetch": "^2.2.1"
what should I do to use fetch upload images? thanks.
You are adding the file to the FormData object incorrectly. isomorphic-fetch wraps github's fetch polyfill. Looking at their docs shows that it should be:
handleFileUpload(event) {
var formData = new FormData();
formData.append('fileName', event.target.files[0]);
fetch('http://your-domain/upload',
{
mode: 'cors',
method: 'POST',
body: formData
}).then(function (response) {
console.log('response: ', response);
});
}
The field name on the server will be whatever you use as the key when appending formData. In the above example it will be 'fileName'. I also don't think you need to set the content-type and file name yourself. It should get set automatically.
In the above example, 'event' is the event fired from the input tag when the user upload the file:
<input type="file" onChange={this.handleFileUpload}/>

handling BLOB and uploading .wav file recorded with recorder.js and HTML5

Reference to this conversation's last answer:
Question-Answer-Session
I am unable to debug and fix files and run code correctly. I see that it is flagged as helpful and correct. Can someone help me understand file structure needed to fix this? I am unable to run this code.
MAIN ISSUE: I am trying to save recorded audio to server.
My BLOB url is: blob:http%3A//localhost/7bc08d6c-8862-45b5-b567-040fd14ef4aa
I am using recorder.js
Thanks!
const constructUploadData = (file: any, data: { audioQueueId: string | Blob; fileName: string | Blob }) => {
const formData = new FormData();
formData.append('audioQueueId', data.audioQueueId);
formData.append('fileName', data.fileName);
if (file) {
formData.append('file', new Blob(file ? [file] : [], { type: file.type }));
}
return formData;
};
const uploadAudioInBackground = (file: any, data: any) => {
return axios.post(`clip/upload`, constructUploadData(file, data), {
headers: { 'Content-Type': 'multipart/form-data' }
});
};

Categories

Resources