Attach file stream / buffer in node.js
Have you ever been in a situation where you wanted to attach a streaming file to an axios call from nodejs? Or you had base64 content of the file and wanted to store it in remote server by passing it down as an attachment? Then this post will guide you with that.
So in the past week I was also at the same situation, where I was getting a stream of pdf file (in which Content-Disposition: attachment; filename=”filename.pdf” was set to make it exclusively downloadable) from a JAVA based service, which I had to convert to a file in node service and attach it as an attachment to another JAVA based service. But the problem is, I was getting a ReadStream and for attaching it I needed a file object.
I have gone through the stack overflow (like most of us) but couldn’t find proper answers. So after some more experimenting, I figured out a way to achieve this.
1. Attaching a ReadStream to axios as a file
Here’s the code sample to do this.
const fs = require('fs')
const Buffer = require('buffer').Buffer
const axios = require('axios')
const FormData = require('form-data')const readFromStream = () => {
/* this is a sample url, can be found here. https://www.learningcontainer.com/sample-pdf-files-for-testing/# */
axios.get('https://www.learningcontainer.com/download/sample-pdf-file-for-testing/?wpdmdl=1566&refresh=60fd3a056fd6e1627208197')
.then((data) => {
let file = fs.writeFileSync('testfile.pdf', data.data ) let form = new FormData() form.append('files', fs.createReadStream('./testfile.pdf'), { filename: 'testfile.pdf' }); axios.post(`your-url-goes-here`, form,
{headers:{"Content-Type": "multipart/form-data; boundary="+form._boundary}}
)
.then((res) => {
console.log("Success : ",res)
})
.catch(err => {
console.log("Error : ",err)
})
})
.catch((err) => {
console.log("Error : ",err)
})
}readFromStream();
2.Attaching a Base64 pdf content to axios as a file.
const fs = require('fs')
const Buffer = require('buffer').Buffer
const axios = require('axios')
const FormData = require('form-data')const readFromBase64 = () => { axios.get('your-api-for-getting-base64-string')
.then((data) => {// let the example string be 'SGksIHRoaXMgaXMgYSBzYW1wbGUgYmFzZTY0IHN0cmluZy4='
// Actual base64 string for a pdf file will be too large.let base64Content = 'SGksIHRoaXMgaXMgYSBzYW1wbGUgYmFzZTY0IHN0cmluZy4=' const buf = new Buffer.from(dbase64Content, 'base64') let form = new FormData() form.append('files', buf, { filename: 'testfile.pdf' }); axios.post(`your-api-for-post-call`, form,
{headers:{"Content-Type": "multipart/form-data; boundary="+form._boundary}}
)
.then((res) => {
console.log("Success : ",res)
})
.catch(err => {
console.log("Error : ", err)
})
})
.catch((err) => {
console.log("Error : ",err)
})
}readFromBase64()
The main point to note here is,
- node doesn’t have FormData by default. so need to use form-data package from npm
- while attaching the buffer / stream to form data, filename should be added. Else it’ll not consider proper MIME type for the file and may result in unwanted behaviour.
- While making axios request, it’s absolute necessary to mention Content-Type and boundary. Else, it’ll throw error.
References :
*Send a File With Axios in Node.js
*Post file from local server
*Cover image — http://www.aisoftwarellc.com/blog/post/writing-custom-streams-in-nodejs---basics/2093
Hope this helps you. If you have any questions and suggestions, let me know in the comments.