Node / Express Create a one-time route / link / download?

How can I create a download link once in nodeJS or Express?

I am trying to find the easiest way to accomplish this. My ideas so far:

Use fs stream to read and then delete the file or Anyway, create a link / route that will be deleted after clicking the download button

Are any of these implementations possible? Is there an easier way?

Any help or sample code would be greatly appreciated!

-Thank

+3
source share
4 answers

Check out this simple implementation:

You save the download information in a file. The file name is the identifier of the download session. The contents of the file is the real path to the file to be downloaded.

:

var fs     = require('fs');
var crypto = require('crypto');
var path   = require('path');

// Path where we store the download sessions
const DL_SESSION_FOLDER = '/var/download_sessions';

/* Creates a download session */
function createDownload(filePath, callback) {
  // Check the existence of DL_SESSION_FOLDER
  if (!fs.existsSync(DL_SESSION_FOLDER)) return callback(new Error('Session directory does not exist'));

  // Check the existence of the file
  if (!fs.existsSync(filePath)) return callback(new Error('File doest not exist'));

  // Generate the download sid (session id)
  var downloadSid = crypto.createHash('md5').update(Math.random().toString()).digest('hex');

  // Generate the download session filename
  var dlSessionFileName = path.join(DL_SESSION_FOLDER, downloadSid + '.download');

  // Write the link of the file to the download session file
  fs.writeFile(dlSessionFileName, filePath, function(err) {
    if (err) return callback(err);

    // If succeeded, return the new download sid
    callback(null, downloadSid);
  });
}

/* Gets the download file path related to a download sid */
function getDownloadFilePath(downloadSid, callback) {
  // Get the download session file name
  var dlSessionFileName = path.join(DL_SESSION_FOLDER, downloadSid + '.download');

  // Check if the download session exists
  if (!fs.existsSync(dlSessionFileName)) return callback(new Error('Download does not exist'));

  // Get the file path
  fs.readFile(dlSessionFileName, function(err, data) {
    if (err) return callback(err);

    // Return the file path
    callback(null, data);
  });
}

/* Deletes a download session */
function deleteDownload(downloadSid, callback) {
  // Get the download session file name
  var dlSessionFileName = path.join(DL_SESSION_FOLDER, downloadSid + '.download');

  // Check if the download session exists
  if (!fs.existsSync(dlSessionFileName)) return callback(new Error('Download does not exist'));

  // Delete the download session
  fs.unlink(dlSessionFileName, function(err) {
    if (err) return callback(err);

    // Return success (no error)
    callback();
  });
}

createDownload() , . sid, URL- , : http://your.server.com/download?sid=<RETURNED SID>.

, /download:

app.get('/download', function(req, res, next) {
  // Get the download sid
  var downloadSid = req.query.sid;

  // Get the download file path
  getDownloadFilePath(downloadSid, function(err, path) {
    if (err) return res.end('Error');

    // Read and send the file here...

    // Finally, delete the download session to invalidate the link
    deleteDownload(downloadSid, function(err) {
      // ...
    });
  });
});

// , .

+7

app.routes. . NodeJS Express .

, :

 var express = require('express');
 var app = express();

 app.get('/download', function(req,res,next){
    res.download('./path/to/your.file');

    //find this route and delete it.
    for(i = 0; i < app.routes.get.length; i++){
        if(app.routes.get[i].path === '/download'){
            app.routes.get.splice(i,1); 
        }
    }
});

app.listen(80);
+1

I would probably outline one route for managing downloads, and then after downloading the file, move or delete it. This way I can prevent a lot of cashing out routes or a lot of small temporary files from two other answers, but YMMV. Something like that:

// say your downloads are in /downloads
app.get('/dl/:filename', function(req, res) {
var fileStream = fs.createReadStream('/downloads' + req.params.filename);
// error handler, ie. file not there...
fileStream.on('error', function(err) {
    if(err) {
        res.status(404); // or something
        return res.end();
    }
});
// here you ow pipe that stream to the response, 
fileStream.on('data', downloadHandler);
// and here delete the file or move it to other folder or whatever, do cleanup
fileStream.on('end', deleteFileHandler);

}

+1
source

I just created a website to solve this problem. If it’s convenient for you to work with the API, my site allows you to create one-time download links: http://linkvau.lt/ I hope this helps!

0
source

All Articles