I'm trying to get a file from the user in my react application and then send that file to my back end and upload it to s3 bucket. I am successfully able to choose a file and it even shows up in the console. But when I send it to the back end, it just shows empty braces.
Here's the code to update the state:
handleInputChange = (event) => {
this.setState({
...this.state,
file: event.target.files[0]
})
}
This is the code to send the file
submit = () => {
console.log(this.state.file)
axios.post(process.env.REACT_APP_SERVER + '/uploadThumbnail', { file: this.state.file, status: true})
.then(response => {
console.log(response)
})
}
Now, I can see the file in console. But in backend, it shows
REQUEST BODY: {file:{}, status: false}
Anyone knows how to solve this issue?
It's not right to send the file as a json.
I guess you are using nodejs backend and maybe using multer for file upload?
To send a file object via api, you have to send it as a form data.
const data = new FormData();
data.append('file', this.state.file);
data.append('status', true);
axios.post(process.env.REACT_APP_SERVER + '/uploadThumbnail', data, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
console.log(response)
})
Related
so I have an API with an endpoint that returns an xlsx file on post request
when I call that API from nextjs server side API it returns a corrupted zip file
but when I call it directly through postman it returns the expected xlsx file.
the call to the API from nextns looks like this:
axios.post(`${process.env.API_URI}`, formData, {
headers: {
...formData.getHeaders(),
},
responseType:"blob"
}).then(response => {
res.status(200).send(response.data)
tmpObj.removeCallback()
}).catch(err => {
console.log(err)
tmpObj.removeCallback()
})
is there a proper way to receive the xlsx file in nextjs API ... Nodejs
update:
eventually I had to set the Content-Type in axios header and the responseType in axios config object
axios.post(`${process.env.API_URI}`, formData, {
headers: {
...formData.getHeaders(),
'Content-Type': 'blob',
},
responseType:"arraybuffer"
}).then(response => {
//createthe buffer in the frontend const buffer = Buffer.from(response.data, 'base64');
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
// res.setHeader('Content-Disposition', 'attachment;filename=SheetJSNode.xlsx')
res.status(200).send(response.data)
}).catch(err => {
console.log(err)
})
I found a website to store videos in cloud storage.
Here's the URL of it: Abyss
They have a very short document and it is written in "cURL" form, it's like this.
curl -F "file=#demo.mp4" up.hydrax.net/MY_API_KEY
So I tried using it with React + ExpressJS.
In my ReactJS, I have a button to submit my video like this:
const handleSubmit = async () => {
let formData = new FormData()
formData.append("file", selectVideo)
await axios.post(
`/film/add-episode/${_id}`,
{
formData,
},
{
headers: {
"content-type": "multipart/form-data",
},
}
)
}
I send that video/mp4 file to my Express POST route that uploads the video.
Here's my POST ExpressJS upload video route controller:
const filmController = {
addEpisode: async (req, res) => {
const { formData } = req.body
try {
console.log(formData) // What I get when passing mp4 from React to Express is an object FormData
//API URL to upload video
const response = await axios.post(
"http://up.hydrax.net/MY_API_KEY_HERE",
{
formData,
},
{
headers: {
"content-type": "multipart/form-data",
},
}
)
console.log(response)
res.json({ msg: "Success add episode" })
} catch (err) {
return res.status(500).json({ msg: err.message })
}
},
}
The reason I tried using axios at the back-end, too, was to get the slug that Abyss generated every time I success uploaded my video from Express to Abyss, I'm planning to save it to my MongoDB with more information, and I get rid of most of the other code like getting id, name, description, etc. for a cleaner look.
Here's how Abyss generates the slug, I need to get it with the post response at Express
But my problem right now is it is just pending my request forever, with no sight of returning the last message or anything, and even in the cloud storage, there was no file uploaded.
Does object FormData can't be read as an mp4 file? Because it seems to be stuck at the POST request I made at Express.
The Scenario
I am running a VueJs client, a NodeJs Restify API Server, and a Tika-server out of the official Docker Image. A user makes a POST call with formData containing a PDF file to be parsed. The API server receives the POST call and I save the PDF on the server. The API server should PUT the file to the unpack/all endpoint on the Tika-server and receive a zip containing a text file, a metadata file, and the set of images in the PDF. I would then process the zip and pass some data back to the client.
The Problem
I create a buffer containing the file to be parsed using let parsingData = fs.createReadStream(requestFilename); or let parsingData = fs.readFileSync(requestFilename);, set the axios data field to parsingData, then make my request. When I get the response from the Tika-server, it seems the Tika-server has treated the request as empty; within the zip, there are no images, the TEXT file is empty, the METADATA.
When I make the following request to the Tika-server via CURL curl -T pdf_w_images_and_text.pdf http://localhost:9998/unpack/all -H "X-Tika-PDFExtractInlineImages: true" -H "X-Tika-PDFExtractUniqueInlineImagesOnly: true"> tika-response.zip, I get a response zip file containing accurate text, metadata, stripped images.
The Code
let parsingData = fs.createReadStream('pdf_w_images_and_text.pdf');
axios({
method: 'PUT',
url: 'http://localhost:9998/unpack/all',
data: parsingData,
responseType: 'arraybuffer',
headers: {
'X-Tika-PDFExtractInlineImages': 'true',
'X-Tika-PDFExtractUniqueInlineImagesOnly': 'true'
},
})
.then((response) => {
console.log('Tika-server response recieved');
const outputFilename = __dirname+'\\output.zip';
console.log('Attempting to convert Tika-server response data to ' + outputFilename);
fs.writeFileSync(outputFilename, response.data);
if (fs.existsSync(outputFilename)) {
console.log('Tika-server response data saved at ' + outputFilename);
}
})
.catch(function (error) {
console.error(error);
});
The Question
How do I encode and attach my file to my PUT request in NodeJs such that the Tika-server treats it as it does when I make the request through CURL?
Axios is sending the request with a content type of application/x-www-form-urlencoded and therefore the file content isn't being detected and parsed.
You can change this by passing either the known content type of the file, or a content type of application/octet-stream to allow Apache Tika Server to auto-detect.
Below is a sample based on your question's code that illustrates this:
#!/usr/bin/env node
const fs = require('fs')
const axios = require('axios')
let parsingData = fs.createReadStream('test.pdf');
axios({
method: 'PUT',
url: 'http://localhost:9998/unpack/all',
data: parsingData,
responseType: 'arraybuffer',
headers: {
'X-Tika-PDFExtractInlineImages': 'true',
'X-Tika-PDFExtractUniqueInlineImagesOnly': 'true',
'Content-Type': 'application/octet-stream'
},
})
.then((response) => {
console.log('Tika-server response recieved');
const outputFilename = __dirname+'/output.zip';
console.log('Attempting to convert Tika-server response data to ' + outputFilename);
fs.writeFileSync(outputFilename, response.data);
if (fs.existsSync(outputFilename)) {
console.log('Tika-server response data saved at ' + outputFilename);
}
})
.catch(function (error) {
console.error(error);
});
I am struggling with a simple media (mp3/mp4) upload to a server using axios.
I have an angular application that creates a formData and send this formData to node server via :
return this.http.post(this.apiURL + '/uploadFile', formData);
My server method looks like this :
app.post('/api/uploadFile', upload.single('file'), (req, res) => {
inputFile = req.file;
let fd = new FormData();
fd.append('file',inputFile.buffer, inputFile.originalname);
axios.post(uploadFileURL , fd, { headers: { 'Content-Type': 'multipart/form-data' } })
.then((response) => {
console.log(response);
})
.catch((error) => {
console.error(error)
})
})
The inputFile contains the original files. The error I get now is that the request is not a multipart request...
I tried as well to define the formData differently :
formData = {
file: {
value: inputFile.buffer,
options: {
filename: inputFile.originalname,
contentType: inputFile.mimetype
}
}
};
Which brought me to a different error : 'Failed to parse multipart servlet request; nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found'
Am I doing something wrong ?
I am wondering if this could be link to the fact that I use const bodyParser = require('body-parser'); for some of my other requests.
Any help would be appreciated!
Thanks
EDIT :
Here is my need and what I've done so far :
I have a web application that allow users to upload media files.
I have to send those files to a server, but I can not use the browser to send the request directly.
I created a nodejs application to realize the proxy task of getting the files from the browser and sending it to my remote server.
As a POC I would like to make pictures of my receipts (gas, shop etc) and use a chatbot to send them to my accounting software. My problem has to do with the sending of the collected receipt (an image) to the accounting software using its API.
The first part (getting the attachment) results in an Arraybuffer with an image. I used one of the NodeJS samples for that (nr 15).
const attachment = turnContext.activity.attachments[0];
const url = attachment.contentUrl;
let image;
axios.get(url, { responseType: 'arraybuffer' })
.then((response) => {
if (response.headers['content-type'] === 'application/json') {
response.data = JSON.parse(response.data, (key, value) => {
return value && value.type === 'Buffer' ? Buffer.from(value.data) : value;
});
}
image = response.data;
}
).catch((error) => {
console.log(error);
});
I am struggling with the second part. Posting the image to the accounting software
const requestConfig = {
headers: {
'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/x-www-form-urlencoded'
}
};
axios.post(postUrl, image, requestConfig)
.then((response) => { console.log(response); }
).catch((error) => {
console.log(error);
});
};
This results in 400. bad request. Probably the API needs a file and I cannot just send the buffer. I tested with Postman and the request is accepted by using application/x-www-form-urlencoded (by using a locally stored image file).
What is best practice to post an image retrieved in a bufferarray?
I think your comment is right on the money that you need to convert it to a file first. The channel isn't an issue because the file will be stored wherever the bot is hosted. The Attachments Sample actually has this code, which gets you close:
fs.writeFile(localFileName, response.data, (fsError) => {
if (fsError) {
throw fsError;
}
// Send the file
const url = '<yourApiUrl>';
const formData = new FormData();
formData.append('file',fs.createReadStream('<pathToFile>'), { knownLength: fs.statSync('<pathToFile>').size });
const config = {
headers: {
...formData.getHeaders(),
'Content-Length': formData.getLengthSync()
}
};
axios.post(url, forData, { headers });
});
I'm not super confident in the // Send the file section only because I can't test against your API. I got most of the code from here.