Expressjs framework has a sendfile()
method. How can I do that without using the whole framework?
I am using node-native-zip to create an archive and I want to send that to the user.
Expressjs framework has a sendfile()
method. How can I do that without using the whole framework?
I am using node-native-zip to create an archive and I want to send that to the user.
Here's an example program that will send myfile.mp3 by streaming it from disk (that is, it doesn't read the whole file into memory before sending the file). The server listens on port 2000.
[Update] As mentioned by @Aftershock in the comments, util.pump
is gone and was replaced with a method on the Stream prototype called pipe
; the code below reflects this.
var http = require('http'),
fileSystem = require('fs'),
path = require('path');
http.createServer(function(request, response) {
var filePath = path.join(__dirname, 'myfile.mp3');
var stat = fileSystem.statSync(filePath);
response.writeHead(200, {
'Content-Type': 'audio/mpeg',
'Content-Length': stat.size
});
var readStream = fileSystem.createReadStream(filePath);
// We replaced all the event handlers with a simple call to readStream.pipe()
readStream.pipe(response);
})
.listen(2000);
Taken from http://elegantcode.com/2011/04/06/taking-baby-steps-with-node-js-pumping-data-between-streams/
net::ERR_CONTENT_LENGTH_MISMATCH
error. –
Collbaith elasticsearch
and still write to a downloadable file by modifying your code? –
Counts You need use Stream to send file (archive) in a response, what is more you have to use appropriate Content-type in your response header.
There is an example function that do it:
const fs = require('fs');
// Where fileName is name of the file and response is Node.js Reponse.
responseFile = (fileName, response) => {
const filePath = "/path/to/archive.rar"; // or any file format
// Check if file specified by the filePath exists
fs.exists(filePath, function (exists) {
if (exists) {
// Content-type is very interesting part that guarantee that
// Web browser will handle response in an appropriate manner.
response.writeHead(200, {
"Content-Type": "application/octet-stream",
"Content-Disposition": "attachment; filename=" + fileName
});
fs.createReadStream(filePath).pipe(response);
return;
}
response.writeHead(400, { "Content-Type": "text/plain" });
response.end("ERROR File does not exist");
});
}
The purpose of the Content-Type field is to describe the data contained in the body fully enough that the receiving user agent can pick an appropriate agent or mechanism to present the data to the user, or otherwise deal with the data in an appropriate manner.
"application/octet-stream" is defined as "arbitrary binary data" in RFC 2046, purpose of this content-type is to be saved to disk - it is what you really need.
"filename=[name of file]" specifies name of file which will be downloaded.
For more information please see this stackoverflow topic.
This helped me. It will start downloading the file as soon as you hit the /your-route
route.
app.get("/your-route", (req, res) => {
let filePath = path.join(__dirname, "youe-file.whatever");
res.download(filePath);
}
Yes download
is also an express method.
Bit Late but express has a helper for this to make life easier.
app.get('/download', function(req, res){
const file = `${__dirname}/path/to/folder/myfile.mp3`;
res.download(file); // Set disposition and send it.
});
In case if you need to send gzipped on the fly file using Node.js natives only:
const fs = require('fs') // Node.js module
const zlib = require('zlib') // Node.js module as well
let sendGzip = (filePath, response) => {
let headers = {
'Connection': 'close', // intention
'Content-Encoding': 'gzip',
// add some headers like Content-Type, Cache-Control, Last-Modified, ETag, X-Powered-By
}
let file = fs.readFileSync(filePath) // sync is for readability
let gzip = zlib.gzipSync(file) // is instance of Uint8Array
headers['Content-Length'] = gzip.length // not the file's size!!!
response.writeHead(200, headers)
let chunkLimit = 16 * 1024 // some clients choke on huge responses
let chunkCount = Math.ceil(gzip.length / chunkLimit)
for (let i = 0; i < chunkCount; i++) {
if (chunkCount > 1) {
let chunk = gzip.slice(i * chunkLimit, (i + 1) * chunkLimit)
response.write(chunk)
} else {
response.write(gzip)
}
}
response.end()
}
© 2022 - 2024 — McMap. All rights reserved.