开发者

How do you upload, stream, and hash a file's contents in Node.js?

I'd like to upload files on my server and name them according to their contents. This should be simple (it is in python), but I am having a hard time figuring out how to do it in Node.js.

I am using express and connect-form, which really just uses formidable. I also see that node has a library called crypto that is very similar to python's h开发者_如何学Pythonashlib. Now I just need to understand how to stream the temp file connect-form gives me and hash it.

This is a Python/Flask(ish) implementation of what I'd like to do.

import hashlib
from Flask import request

def upload():
  file = request.files['file']
  hash = hashlib.sha256()
  name, ext = file.filename.rsplit('.', 1)
  try:
    for chunk in file.chunks()
      hash.update(chunk)
  finally:
    file.seek(0)
    new_name = "%s.%s" % (hash.hexdigest(),ext)
    file.save(os.path.join(UPLOAD_DIR, new_name))

I have seen a lot of these toy answers that just print out the file's name, but none that actually read and write the data.


Here it is in coffee-script in all its glory.

app.post '/upload', (request, response, next) ->
    request.form.complete (error, fields, files) ->
        if error
            next error
        else
            file = files.file
            [kind, extension] = file.type.split '/'
            hash = crypto.createHash 'sha256'
            stream = fs.createReadStream file.path,
                encoding:'binary'
            stream.addListener 'data', (chunk) ->
                hash.update chunk
            stream.addListener 'close', ->
                digest = hash.digest 'hex'
                new_filename = "#{digest}.#{extension}"
                new_path = "#{UPLOAD_DIR}/#{new_filename}"
                fs.rename file.path, new_path
                response.end new_filename

Rather than hacking the hash calculation into formidable, which would likely be more efficient but far more complicated, I opted to just re-read the file from its temporary location and hash that. Then instead of pumping it like in other examples, I just renamed the temp file into its new location.


you can save a file like this:

var fs = require('fs'),
    util = require('util'),
    crypto = require('crypto');

// ...

req.form.complete(function (err, fields, files) {

    // ...

    var ext = files['content[media]']['filename'].split('.');
        ext = ext[ext.length-1];
        ext = ext.toLowerCase();

    var newFileName = req['connection']['remoteAddress'] + req['connection']['remotePort'] + Date.now();
    newFileName = crypto.createHash('md5').update(newFileName).digest("hex");
    newFileName += '.' + ext;

    var is = fs.createReadStream(files['content[media]']['path']);
    var os = fs.createWriteStream(app.set('dataDir') + '/' + newFileName);

    // copy file to public folder
    util.pump(is, os, function(error) {
        if (error) {
            console.log("Error copying file to public ... " + error);

            res.redirect("back");
            return;
        }
        else {
            // delete temp file
            fs.unlinkSync(files['content[media]']['path']);

            res.redirect('....');
        }
    });

});
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜