Node/Express生成一次性路由/链接/下载?

gba*_*hik 6 javascript download node.js express

我如何在nodeJS或Express中创建一次性下载链接?

我正在努力找到实现这一目标的最简单方法.我到目前为止的想法是:

使用fs流读取然后删除文件或以某种方式生成一个单击下载按钮后删除的链接/路由

这些实现是否可行?有更简单的方法吗?

任何帮助或示例代码将不胜感激!

-谢谢

kar*_*son 11

检查这个简单的实现:

您将下载的信息存储在一个文件中.文件名是下载会话ID.文件内容是要下载的文件的真实路径.

使用这三个函数来管理下载会话的生命周期:

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();
  });
}
Run Code Online (Sandbox Code Playgroud)

用于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) {
      // ...
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

使用此方法,您不必创建/移动/删除大型下载文件,这可能会导致响应缓慢和不必要的资源消耗.