How to recive uploded file in nodejs - javascript

i have a redux-from submission, console log look like this
{
id: "x",
parentId: "b",
editing: true,
logo: FileList,
}
Logo FileList contains my uploaded file name and file, i think
0: File(19355) {name: "11964821.jpeg", lastModified: ......
using fetch to send to nodejs, image contain my files and above data
function Update(image) {
const requestOptions = {
method: 'POST',
headers: { ...authHeader(), 'Content-Type': 'application/x-www-form-urlencoded' },
body: JSON.stringify(image)
};
return fetch(`${apiUrl}/API`, requestOptions).then(handleResponse)
.then( data => { return data; });
}
but this data not receiving nodejs, because is tried re.file etc.. its shows undefined
app.post('/image', upload.single('logo'), function (req, res, next) {
})
include formdata
const onSubmit = (image, dispatch)=>{
var formData = new FormData();
formData.append('logo',image.logo[0]);
var imageNew = {...image,formData};
dispatch(imageActions.companyProfileLogoUpdate(imageNew)) ;
}
now log is
formData: FormData {}
id: "5c66478b0814720a4365fe72"
logo: FileList {0: File(19355), length: 1}
parentId: "5c66478b0814720a4365fe71"

let formData = new FormData();
formData.append('logo' , {{your image file}}
// upload file as
let result = await sendServerRequestForForm(url,formData);
function sendServerRequestForForm(url,data) {
var promise = new Promise(function(resolve) {
resolve($.ajax({
url,
method : 'POST',
data,
processData: false,
contentType: false,
success: function(data) {
return data
},
error: function (err) {
try{
let responseStatus = err.responseJSON
// watch your response
}catch (e) {
console.log('Field to get response');
}
}
}));
});
return promise
}

for fetch API you can try this
let formData = new FormData();
formData.append('logo', fileList[0]);
fetch(url, {
method: 'post',
body: data,
})
.then(…);

move formData to fetch file and remove header content type, Try this
function Update(image) {
var formData = new FormData();
formData.append('logo',image.logo[0]);
const requestOptions = {
method: 'POST',
headers: { ...authHeader() },
body: formData
};
return fetch(`${apiUrl}/API`, requestOptions).then(handleResponse)
.then( data => { return data; });
}

First thing is for using fetch api for post content-type header should match typeof body. since your body is json stringified your contentType header should be 'application/json' . more about this .
Second. since you want to upload an image which a file you should use FormData without requirement of setting contentType: like below:
let formData = new FormData();
formData.append('logo', image.logo[0]);
const requestOptions = {
method: 'POST',
body: formData
};
fetch(`${apiUrl}/API`, requestOptions)
.then(handleResponse)...

Related

Upload file to s3 using presigned post url in the server

TDLR: Using s3 presigned post url to upload file to s3. Works fine on the browser but fails on the server.
I have a simple lambda function that generates presigned post url that can be consumed either in the browser or in the server.
During testing I noticed that the upload works fine one the browser but fails if I try to upload a file from a server even tho the code is identical.
The error i get is:
You must provide the Content-Length HTTP header
Detailed error:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>MissingContentLength</Code>
<Message>You must provide the Content-Length HTTP header.</Message>
<RequestId>JP75YMFARK0G3X5Z</RequestId>
<HostId>toHsKmxmVYYAtac94cQoy8wXoregKG3PNBm97c3gQewEmKxLggcumTAP882T/pJNWx/lxRgH98A=</HostId>
</Error>
Request failed with status code 411
I checked online and found many threads about this issue but unfortunately not a single suggestion helped me.
Code I am running in the server
const axios = require('axios');
const { createReadStream, readFileSync } = require('fs');
const FormData = require('form-data');
const getPostPresignedUrl = async () => {
var config = {
method: 'post',
url: LAMBDA_GET_URL,
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
key: 'test-2.jpg',
fileType: 'image/jpeg',
}),
};
const {
data: { data },
} = await axios(config);
return data;
};
const uploadFileToS3 = async (fields, url) => {
const formData = new FormData();
Object.entries(fields).map(([key, value]) => {
formData.append(key, value);
});
const file = createReadStream('./test-1.jpg');
formData.append('file', file);
try {
const { data } = await axios({
url,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
});
} catch (error) {
if (error instanceof axios.AxiosError) {
console.log(error.response.data);
}
console.log(error.message);
}
};
const init = async () => {
const { fields, url } = await getPostPresignedUrl();
await uploadFileToS3(fields, url);
};
init();
Code I am running in the browser:
const form = document.getElementById('form');
const input = document.getElementById('file');
const getPostPresignedUrl = async (name) => {
var config = {
method: 'post',
url: LAMBDA_GET_URL,
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
key: name,
fileType: 'image/jpeg',
}),
};
const {
data: { data },
} = await axios(config);
return data;
};
const uploadFileToS3 = async (fields, url, file) => {
const formData = new FormData();
Object.entries(fields).map(([key, value]) => {
formData.append(key, value);
});
formData.append('file', file);
try {
const { data } = await axios({
url,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
});
} catch (error) {
if (error instanceof axios.AxiosError) {
console.log(error.response.data);
}
console.log(error.message);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const file = input.files[0];
const data = await getPostPresignedUrl(file.name);
await uploadFileToS3(data.fields, data.url, file);
};
form.onsubmit = handleSubmit;

including image in request body as binary data

I need to include the image as binary data in my uploading request using multipart form data, and it seems not working, any advise will be appreciated.
my code:
const [selectedFile, setSelectedFile] = useState(null);
const handleSubmit = async (event) => {
event.preventDefault();
const formData = new FormData();
formData.append('selectedFile', new Blob([selectedFile], { type: 'application/octet-stream' }));
const data = {
uploadLink,
formData,
};
const headers = {
'Content-Type': 'application/octet-stream' ,
Accept: 'application/vnd.vimeo.*+json;version=3.4',
};
try {
await axios
.post(`${backendPostPath}/thumbnail-upload`, data, {
headers,
})
.then((response) => {
applyThumbnial();
console.log(response);
});
} catch (error) {
console.log(error);
}
};
const handleFileSelect = (event) => {
setSelectedFile(event.target.files[0]);
};
include formData as axios data parameter instead of your data object, so you can also include uploadLink in the formData:
const formData = new FormData();
formData.append('selectedFile', new Blob([selectedFile], { type: 'application/octet-stream' }));
formData.append('uploadLink', uploadLink)
//...
await axios
.post(`${backendPostPath}/thumbnail-upload`, formData, {
headers,
})

Why does 'formData' not work in 'axios 0.26.1' in react native Android emulator?

I have use expo-image-picker and axios 0.26.1. formData in axios version 0.26.1 isn't work. when using formData, data is not sent to the api
downgrade axios to version 0.24.0 but I get this error when sending formData in Android emulator.
Error: Network Error
formData:
export const sendRequest = (url, response, method, formData) => {
return axios({
url,
method,
data: method !== "get" ? formData : null,
headers: {
Authorization: `Bearer ${response.data.access}`,
transformRequest: (data, headers) => {
return formData;
},
},
});
const formData = new FormData();
const imageUri = image.value.uri;
const newImageUri = "file:///" + imageUri.split("file:/").join("");
formData.append("photo", {
uri: newImageUri,
type: mime.getType(newImageUri),
name: newImageUri.split("/").pop(),
});
data.append("title", title);
can you help me please?
This bug has been posted on Axios GitHub issues and apparently it is present since 0.25.0. I had to roll back to version 0.24.0 to make it work. However, this issue has been closed with the following solutions.
Method 1:
const formData = new FormData();
const response = await axios.post('/URL', formData, {
headers: {
...formData.getHeaders()
}
});
Method 2:
axios.post(url, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
transformRequest: formData => formData,
})
You can check the issue here

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)

AJAX not uploading images to backend service

Working on a requirement to upload images to AWS instance. UI and service is separated and connects via REST. Service is in nodejs. from UI we are making a ajax call to backend service to upload the images to AWS.
The problem:
When I upload the images via POSTMAN request, I can see that response as uploaded with files properly uploaded in AWS.
Whereas when I upload images via AJAX call, I get no response in browser, and also the images are not uploaded in aws.
Below is the piece of code in ajax:
var formData = new FormData();
formData.append('image', $('#tx_file_programa')[0]);
$.ajax({
method: 'POST',
type: "POST",
url: 'http://10.0.0.95:9999/photo/1',
contentType: false,
processData: false,
async: false,
cache: false,
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token );
},
data: formData,
success: function (data) {
console.log('response from server is : ', data);
}
//dataType: 'json'
});
This is the backend service.
server.post('/photo/:count', function (req, res) {
if (req.getContentType() == 'multipart/form-data') {
var form = new formidable.IncomingForm(),
files = [], fields = [];
var result = [];
var noOfFiles = req.params.count;
var count = 0;
console.log('noOfFiles', noOfFiles);
form.on('field', function(field, value) {
fields.push([field, value]);
console.log(fields);
})
form.on('progress', function(bytesReceived, bytesExpected) {
console.log('err');
});
form.on('error', function(err) {
console.log('err',err);
});
form.on('aborted', function() {
console.log('aborted', arguments);
});
new Promise(function(resolve, reject) {
var result = [];
form.onPart = function (part) {
var data = null;
const params = {
Bucket: 'xxxxx',
Key: uuidv4() + part.filename,
ACL: 'public-read'
};
var upload = s3Stream.upload(params);
upload.on('error', function (error) {
console.log('errr', error);
});
upload.on('part', function (details) {
console.log('part', details);
});
upload.on('uploaded', function (details) {
let extension = details.Location.split('.');
if(['JPG', 'PNG'].indexOf(extension[extension.length - 1].toUpperCase()) > -1) {
var ext = extension[extension.length - 1];
count++;
result.push(details.Location);
if(count == noOfFiles) {
resolve(result);
}
}
});
part.pipe(upload);
}
}).then(function(result){
console.log('end', result);
res.writeHead(200, {'content-type': 'text/plain'});
res.end('received files:\n\n ' + util.inspect(result));
})
form.parse(req, function (err, fields, files) {
})
return;
} else {
BadRequestResponse(res, "Invalid request type!");
}
})
#user3336194, Can you check with this, this is working thins
var appIconFormData = null
$(":file").change(function () {
var file = this.files[0], name = file.name, size = file.size, type = file.type;
var imageType = new Array("image/png", "image/jpeg", "image/gif", "image/bmp");
if (jQuery.inArray(type, imageType) == -1) {
return false;
} else {
appIconFormData = new FormData();
appIconFormData.append('appimage', $('input[type=file]')[0].files[0]);
}
});
$.ajax({
url: 'your/api/destination/url',
type: 'POST',
data: appIconFormData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
console.log(data)
},
error: function (e) {
}
});
I think the way you are sending formdata is not correct.
Try these 2 ways:
You can give your whole form to FormData() for processing
var form = $('form')[0]; // You need to use standard javascript object here
var formData = new FormData(form);
or specify exact data for FormData()
var formData = new FormData();
// Attach file
formData.append('image', $('input[type=file]')[0].files[0]);

Categories

Resources