Reputation: 482
I am currently building a web app in node with angular front end. I want to add an option where the client can download generated excel files. Currently I have some working code that can generate several excel file which are currently stored in a map on the server. What I want is that the user can now download these files and when it is downloaded, the files will be deleted. I don't know what is best practice for this. Here are some options I have been considering:
Any suggestions on what I could do and how I can implement it?
Edit: I am generating the excel files with the node package 'exceljs'
Thanks in advance!
Edit: Thanks to the given answers and a little more googling I have found the answer I was looking for. I have slightly modified it because I am now sending a zip file but it will also work with an excel file.
For sending a zip-file in node:
var archive = archiver.create('zip', {});
archive.pipe(res);
archive.directory(dateDir, name).finalize();
For sending an excel-file in node:
res.setHeader('Content-Type', 'application/vnd.ms-excel');
res.setHeader('Content-disposition', 'attachment; filename=test.xlsx');
workbook.xlsx.write(res).then(function () {
res.end();
});
For receiving the file in angular I used FileSaver.js as following:
$http({
url: url,
method: 'POST',
headers: headers,
data: data,
responseType: 'arraybuffer'
})
.success(function (data, status, headers) {
/*var fileName = headers('Content-Disposition');
console.log(fileName);*/
saveAs(new Blob([data], {type: contentType}), 'download.zip');
})
Upvotes: 3
Views: 5885
Reputation: 24128
Following the solution of @Brij Raj Singh - MSFT, I think you can implement it in the two steps of individual urls for AngularJS.
First step: AngularJS send an http request to URL A for generating that it render data to generate a file, and return back the JSON data include URL B with the generated file name for downloading.
// write to a file
var workbook = createAndFillWorkbook();
var filename = '<yourfilename>';
// response a url with file name generated
res.write('{"download_url": "/download/"+filename, "name": "XXX"}');
AngularJS render the JSON data received to a link tag <a href="/download/xxx.xlsx">XXX</a>
.
Second step: User click the download link and the server send back a file response, then delete the file after downloaded.
var file = __dirname + '/upload-folder/<yourfilename extracted from url>.xlsx';
var filename = path.basename(file);
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(file);
filestream.pipe(res);
filestream.on('close', function (error) {
if (err) return res.send(500);
fs.unlink(__dirname + '/upload-folder/<yourfilename>.xlsx');
});
fs.unlink(file);
Upvotes: 1
Reputation: 5113
So what you exactly want is that user clicks a button a file gets generated (excel file), and gets downloaded and it doesn't remain in the server (purely because it doesn't serve any more purpose)
var path = require('path');
var mime = require('mime');
// write to a file
var workbook = createAndFillWorkbook();
workbook.xlsx.writeFile(filename)
.then(function() {
var file = __dirname + '/upload-folder/<yourfilename>.xlsx';
var filename = path.basename(file);
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(file);
filestream.pipe(res);
filestream.on('close', function (error) {
if (err) return res.send(500);
fs.unlink(__dirname + '/upload-folder/<yourfilename>.xlsx');
});
});
Here right after the file is created, we pipe the response out to the user, and when stream is closed we are deleting the file, I just wrote the pseudo code
Upvotes: 1