【问题标题】:How can I get the checksum of a (large) file using ExpressJS/Connect/Crypto?如何使用 ExpressJS/Connect/Crypto 获取(大)文件的校验和?
【发布时间】:2013-10-01 06:56:47
【问题描述】:

我需要在文件上传时为大文件 (.ISO) 生成校验和。我正在使用 ExpressJS/Connect 通过 POST(多部分)处理上传请求

  //express setup app.js
  app.use('/upload',express.bodyParser({
      defer : true, //enable progress event
      keepExtensions : true,
      limit : app.locals.fileLimit,
      uploadDir : path.join( __dirname, '..', 'tmp'),
      hash : true //this doesnt appear to do anything
  }));

  //express route routes.js
  app.post("/upload", function(req, res){

      var fs     = require('fs');
      var format = require('util').format;

      req.form.hash = true; //this doesnt return the hash for some reason

      req.form.on('fileBegin', function(err) {
         log.info("Starting new upload...");
      });

      req.form.on('file', function(name, file) {
          fs.rename(file.path, req.form.uploadDir + "/" + file.name);
        console.info(file);
      });

      req.form.on('error', function(err) {
         log.error('error',err);
         req.resume();
      });



      req.form.on('field', function(field, value) {
         log.info("Passed Field (%s=%s)...",field,value);
      });

      //this part event never gets called for some reason but
      //I imagine this is where you might do a hash update
      req.form.on('part', function(part){
        console.log('PART upload %s %s', part.name, part.filename);
        var out = fs.createWriteStream('../tmpstrm/' + part.filename);
        part.pipe(out);
      });


      req.form.on('progress', function(bytesReceived, bytesExpected) {
          var percent = (bytesReceived / bytesExpected * 100) | 0;
          console.info( "PROGRESS :"+ ((bytesReceived / bytesExpected)*100) + "% uploaded");
      });

      req.form.on('end', function() {
          var fileInfo = format('\nuploaded %s (%d Kb) to %s as %s'
            , req.files.upload.name
            , req.files.upload.size / 1024 | 0
            , req.files.upload.path
            , req.body.title);

          res.locals.fileInfo = fileInfo; //renders info in jade

          res.render('media/index');
      });

  });

我找不到关于我的特定问题的太多信息;这可能不是典型的用例。但是我发现的一个问题有一个简单的例子how to update the hash on a data event

var hash = crypto.createHash('sha1');
var data = // incoming file data

data.on('data', function(chunk){
  hash.update(chunk);
});
data.on('end', function(){
  var sha = hash.digest('hex');

  // Do something with it
})

我是流媒体、块等方面的新手,因此非常感谢这里的一些指导。

【问题讨论】:

    标签: node.js file-upload express checksum


    【解决方案1】:

    在我的 writers-digest npm 模块源代码中有一些示例代码可能对您有所帮助:

    https://github.com/focusaurus/writers-digest/blob/ab52ffca6e989ca657dc449e05ff258c428fa3af/index.js#L38

    但基本上你有两种方法:

    1. 允许 bodyParser 将 HTTP 请求正文流式传输到文件系统,然后通过流式传输来自文件系统的数据来计算校验和(以 writers-digest 代码为例)。

    2. 您可以尝试在实际 HTTP 请求正文到达时通过将事件处理函数绑定到 req 对象 dataend 事件来计算校验和。当 bodyParser 也将其流式传输到磁盘时,您应该能够做到这一点。只需确保事件绑定得足够早,这样您就不会错过任何块。

    【讨论】:

    • 谢谢!您是有关 NodeJS 问题的常规且有用的资源。一些背景信息——这是我第一次尝试让它工作,在后续版本中,这应该将写入流重定向到网络上的另一台服务器,因此文件不会存储在机器上运行节点。您对如何处理有任何想法吗?这两种方法仍然适用吗?
    • 所以是的,您可以将流代理到目标服务器,但请记住,这是另一个故障点和不可靠性。我会坚持使用更简单的存储和转发模型,但理论上您可以将文件内容代理到上游服务器(或者甚至可以配置 nginx 为您执行此操作)。不过,很难将这么大的架构问题作为 stackoverflow 评论来解决。也许可以通过airpair.com 会话来完成。
    猜你喜欢
    • 2023-04-03
    • 2015-04-30
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多