Why is my server not receiving my uploaded file? - javascript

In Postman I can send files and they are received fine. My client [react] isn't managing to and my server always receives undefined.
Here is my handleSubmit function and form:
const handleSubmit = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("file", e.target.file.files[0]);
dispatch(upload(formData));
};
return (
// form for uploading a file
<form onSubmit={handleSubmit} encType="multipart/form-data">
<input type="file" name="file" />
<button type="submit">Upload</button>
</form>
);
And here is my axios call:
const API_URL = "/api/uploads/";
const upload = async (file) => {
const formData = new FormData();
formData.append("file", file);
const response = await axios.post(API_URL, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
withCredentials: true,
});
return response.data;
};
am I doing something wrong? I've been debugging for hours...

Related

Why won't file uploads work on the browser despite it working in Postman?

I'm not sure why when making a POST request on Postman, I'm successfully storing the URLs in the DB by grabbing the file and retrieving its name.
But when I try it on the browser, I get a 500 error. The auth token's coming back correctly, the logged data is also containing the correct information so it's not entirely clear to me what I'm doing wrong even though I'm doing it exactly the same way as how I'm doing it in Postman and it works fine there.
In the server logs I see an error that says: Call to a member function getClientOriginalName() on null but as mentioned before - the upload works fine on Postman.
What could be issue?
Here's my JS:
const [selectedFile, setSelectedFile] = useState(null);
let authToken = localStorage.getItem('token');
const onFormSubmit = (e) => {
e.preventDefault()
fileUpload(selectedFile);
}
const onChange = (e) => {
let files = e.target.files || e.dataTransfer.files;
if (!files.length) {
return;
}
createImage(files[0]);
}
const createImage = (file) => {
let reader = new FileReader();
reader.onload = (e) => {
setSelectedFile(e.target.result);
};
reader.readAsDataURL(file);
}
const fileUpload = (selectedFile) => {
const url = 'http://localhost:8005/api/file-upload';
const formData = {file: selectedFile}
const headers = {
"Accept": 'application/json',
"Authorization": `Bearer ${authToken}`
}
console.log(authToken);
console.log(formData);
console.log(headers);
JSON.stringify(formData);
axios.post(url, formData, {
headers: headers
}).then(resp => {
console.log(resp);
}).catch(error => {
console.log(error);
});
}
return (
<form>
<input type="file" onChange={onChange} name="userUpload" required/>
<Button variant="primary" onClick={onFormSubmit}>Upload!</Button>
</form>
);
you should check your header content-type that should be set to
multipart/form-data

Why am I getting a 500 when uploading file via the browser but not via Postman? [duplicate]

Using raw HTML when I post a file to a flask server using the following I can access files from the flask request global:
<form id="uploadForm" action='upload_file' role="form" method="post" enctype=multipart/form-data>
<input type="file" id="file" name="file">
<input type=submit value=Upload>
</form>
In flask:
def post(self):
if 'file' in request.files:
....
When I try to do the same with Axios the flask request global is empty:
<form id="uploadForm" enctype="multipart/form-data" v-on:change="uploadFile">
<input type="file" id="file" name="file">
</form>
uploadFile: function (event) {
const file = event.target.files[0]
axios.post('upload_file', file, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
If I use the same uploadFile function above but remove the headers json from the axios.post method I get in the form key of my flask request object a csv list of string values (file is a .csv).
How can I get a file object sent via axios?
Add the file to a formData object, and set the Content-Type header to multipart/form-data.
var formData = new FormData();
var imagefile = document.querySelector('#file');
formData.append("image", imagefile.files[0]);
axios.post('upload_file', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
Sample application using Vue. Requires a backend server running on localhost to process the request:
var app = new Vue({
el: "#app",
data: {
file: ''
},
methods: {
submitFile() {
let formData = new FormData();
formData.append('file', this.file);
console.log('>> formData >> ', formData);
// You should have a server side REST API
axios.post('http://localhost:8080/restapi/fileupload',
formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then(function () {
console.log('SUCCESS!!');
})
.catch(function () {
console.log('FAILURE!!');
});
},
handleFileUpload() {
this.file = this.$refs.file.files[0];
console.log('>>>> 1st element in files array >>>> ', this.file);
}
}
});
https://codepen.io/pmarimuthu/pen/MqqaOE
If you don't want to use a FormData object (e.g. your API takes specific content-type signatures and multipart/formdata isn't one of them) then you can do this instead:
uploadFile: function (event) {
const file = event.target.files[0]
axios.post('upload_file', file, {
headers: {
'Content-Type': file.type
}
})
}
Sharing my experience with React & HTML input
Define input field
<input type="file" onChange={onChange} accept ="image/*"/>
Define onChange listener
const onChange = (e) => {
let url = "https://<server-url>/api/upload";
let file = e.target.files[0];
uploadFile(url, file);
};
const uploadFile = (url, file) => {
let formData = new FormData();
formData.append("file", file);
axios.post(url, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
}).then((response) => {
fnSuccess(response);
}).catch((error) => {
fnFail(error);
});
};
const fnSuccess = (response) => {
//Add success handling
};
const fnFail = (error) => {
//Add failed handling
};
This works for me, I hope helps to someone.
var frm = $('#frm');
let formData = new FormData(frm[0]);
axios.post('your-url', formData)
.then(res => {
console.log({res});
}).catch(err => {
console.error({err});
});
this is my way:
var formData = new FormData(formElement);
// formData.append("image", imgFile.files[0]);
const res = await axios.post(
"link-handle",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
How to post file using an object in memory (like a JSON object):
import axios from 'axios';
import * as FormData from 'form-data'
async function sendData(jsonData){
// const payload = JSON.stringify({ hello: 'world'});
const payload = JSON.stringify(jsonData);
const bufferObject = Buffer.from(payload, 'utf-8');
const file = new FormData();
file.append('upload_file', bufferObject, "b.json");
const response = await axios.post(
lovelyURL,
file,
headers: file.getHeaders()
).toPromise();
console.log(response?.data);
}
There is an issue with Axios version 0.25.0 > to 0.27.2 where FormData object in a PUT request is not handled correctly if you have appended more than one field but is fine with one field containing a file, POST works fine.
Also Axios 0.25.0+ automatically sets the correct headers so there is no need to specify Content-Type.
For me the error was the actual parameter name in my controller... Took me a while to figure out, perhaps it will help someone. Im using Next.js / .Net 6
Client:
export const test = async (event: any) => {
const token = useAuthStore.getState().token;
console.log(event + 'the event')
if (token) {
const formData = new FormData();
formData.append("img", event);
const res = await axios.post(baseUrl + '/products/uploadproductimage', formData, {
headers: {
'Authorization': `bearer ${token}`
}
})
return res
}
return null
}
Server:
[HttpPost("uploadproductimage")]
public async Task<ActionResult> UploadProductImage([FromForm] IFormFile image)
{
return Ok();
}
Error here because server is expecting param "image" and not "img:
formData.append("img", event);
public async Task<ActionResult> UploadProductImage([FromForm] IFormFile image)

"Multipart: Boundary not found": File upload issue with Reactjs, Express, Multer and S3

I am trying to upload an image from my React frontend, but running into an Unprocessable Entity error. The server route works as I have successfully uploaded an image through Postman.
const handleFileUpload = async (file: any) => {
const imageData = new FormData();
imageData.append("image", file[0]);
const config = {
method: "POST",
headers: {
"Content-Type": "multipart/form-data",
Accept: "application/json",
},
body: imageData,
};
try {
const req = await fetch(url, config);
if (req.ok) {
const res = await req.json();
console.log(res);
}
} catch (err) {
console.log(err);
}
};
Input:
<input
type="file"
accept="image/png, image/jpeg"
onChange={(e: any) => { handleFileUpload(e.target.files ? e.target.files : url); }}
/>
Here is my working example:
// the input
<input
type="file"
accept="image/x-png,image/jpeg,image/gif"
className={classes.uploadInput}
ref={ref => upload = ref}
onChange={e => uploadAvatar(e.target.files[0])}
/>
// redux action
const uploadAvatar = avatar => ({type: ActionType.TRY_CHANGE_AVATAR, avatar})
// redux-saga
const data = new FormData()
data.append('avatar', avatar)
// axios request
const result = yield axios.post(API_LINK, data)
// in my php I have this headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
// and
if (!move_uploaded_file($_FILES['avatar']['tmp_name'], $uploadFolder . $filename))
...
// to upload it.
This is just an example not really an answer to your question, but still i hope this helps in some way.
To solve, I removed the headers from the POST request so that fetch would automatically generate them. Server wise, I needed to set a limit on bodyParser to 50mb. Here are my edits:
const handleFileUpload = async (file: any) => {
const imageData = new FormData();
imageData.append("image", file);
const config = {
method: "POST",
body: imageData,
};
try {
const req = await fetch(url, config);
if (req.ok) {
const res = await req.json();
console.log(res);
if (res.success) {
setURL(res.user.profilePicture);
}
}
} catch (err) {
console.log(err);
}
};

Sending file to server API using fetch POST method

I'm trying to send .xml file from my PC to a server, but im getting this error:
POST https://localhost:44391/api/edit net::ERR_ABORTED 415
File state
const [file, setFile] = useState();
Input and button
<input type="file" id="file" onChange={(e) => setFile(e.target.files[0])} />
<button onClick={send}>DASD</button>
Onclick function
const send = async () => {
if (file) {
let formData = new FormData();
formData.append('file', file);
console.log(formData);
await fetch("https://localhost:44391/api/edit",
{ method: "POST", body: formData });
}
}
Remove the content type from the header, as the content type is not 'text/xml it should be multipart/form-data.
Fetch api will automatically add the header based on the content. Which will be something Content-Type: multipart/form-data; boundary=—-WebKitFormBoundaryfgtsKTYLsT7PNUVD
const send = async () => {
if (file) {
let formData = new FormData();
formData.append("file", file);
console.log(formData);
await fetch("https://localhost:44391/api/edit", {
method: "POST",
body: formData
});
}
};

My submit function responds with Bad Gateway 502

I am trying to set up "Cloudinary" for image uploads from my React app.
My submit function keeps responding with: "Bad Gateway 502" and "SyntaxError: Unexpected end of input".
I'm assuming something is wrong with my headers, but I can't find the issue...
handleFileSelect = (e) => {
this.formValid()
this.setState({
picture: e.target.files[0] })
}
submit(){
const CLOUDINARY_URL=
"https://api.cloudinary.com/v1_1/dvz27u2gu/image/upload"
const CLOUDINARY_UPLOAD_PRESET= "jshvp3nh"
const obj = Object.assign({}, this.state);
const formData = new FormData();
formData.append("file", obj.picture);
formData.append("upload_preset", CLOUDINARY_UPLOAD_PRESET);
fetch(CLOUDINARY_URL,{
mode: 'no-cors',
method:'post',
headers: { "Content-Type": "application/x-www-form-urlencoded"},
body:formData,
})
.then((res)=>{return res.json()})
.then(data=>console.log(data))
.catch(err=>console.log(err));
}
You can try something like the following:
<div><input type="file" onChange={this.submit}/></div>
submit = (e) => {
var file = e.target.files[0];
var data = new FormData();
data.append('upload_preset', 'jshvp3nh');
data.append('file', file);
data.append('cloud_name', 'dvz27u2gu');
const config = {
method: "POST",
body: data
};
var imgurl = "https://api.cloudinary.com/v1_1/dvz27u2gu/raw/upload";
fetch(imgurl, config)
.then(responseData => {
console.log('here');
console.log(JSON.stringify(responseData, null, 4));
console.log(responseData);
})}
This is how it worked for me.
const CLOUDINARY_URL= "https://api.cloudinary.com/v1_1/dvz27u2gu/image/upload"
const CLOUDINARY_UPLOAD_PRESET= "jshvp3nh"
const obj = Object.assign({}, this.state);
const formData = new FormData();
formData.append("file", obj.picture);
formData.append("api_key", "xx")
formData.append("api_secret", "xx")
formData.append("upload_preset", CLOUDINARY_UPLOAD_PRESET);
formData.append("timestamp", (Date.now() / 1000) | 0);
fetch(CLOUDINARY_URL,{
method:'POST',
body: formData,
})
.then((res)=>{return res.json()})
.then((data)=>{
obj.img_url_cloudinary=data.secure_url;
this.sendForm(obj);
}).catch(err=>console.log(err));;

Categories

Resources