NodeJS教程–基于ExpressJS框架的文件上传

本文是翻译的一篇文章,原文地址:Handle File Uploads in Express (Node.js).

在NodeJS发展早期上传文件是一个较难操作的功能,随后出现了formidable。它开了一个好头,然而上传文件仍然不是那么容易。在此之后又出现了基于原文作者的教程(tutorial on handling POST requests in Express)而实现的工具connect-form。它让文件上传的过程显得简单了一些。

随着NodeJS社区的飞速发展,让上传文件这个功能变得简单得以实现肯定不会需要太长时间。现在这个功能已经得以实现—在ExpressJS中你可以很容易的上传文件。

在Express中上传文件时不再需要依赖其他的模块,文件上传可以很好工作于Express框架内。就像使用req.body一样,现在你可以使用req.files来获得你上传的文件中的具体信息。

如果你不需要指定上传文件的目录,那么你不需要对app.js做任何的改变,文件将默认上传到’/tmp’目录。但是如果你希望对你上传的文件指定特定目录,你仅仅需要修改一下内容:

app.use(express.bodyParser());

修改为 :

app.use(express.bodyParser({uploadDir:'./uploads'}));

这一配置项可以再ExpressJS的V2.5.4之后的版本中发现,具体可以参看ExpressJS的源代码,具体在express.bodyParser的第16行。在上面的示例中。文件将被上传到与express应用同级目录下的uploads目录中。

为了更好说明在POST过程中文件上传时一些细节,我们建立如下的一个表单提交页面:

<form method="post" enctype="multipart/form-data" action="/file-upload">
  <input type="text" name="username">
  <input type="password" name="password">
  <input type="file" name="thumbnail">
  <input type="submit">
</form>

服务端在处理上面的表单提交时的方法如下:

app.post('/file-upload', function(req, res, next) {
  console.log(req.body);
  console.log(req.files);
});

看看就是这么简单!

在上面的示例中,我们可以通过调用req.files.thumbnail对象来获得我们上传的文件的具体信息,对象的名称取决你上在form表单的定义。如上所示,我们使用的名称是thumbnail,因此我们可以通过req.files.thumbnail来获得它的信息。

一个文件包含以下常用的属性信息:

  • size —- 文件大小(bytes)
  • path —- 文件上传后的路径
  • name —- 文件的原始文件名称.
  • type —-文件类型

针对上面的示例来说, 文件大小:req.files.thumbnail.size
文件类型: req.files.thumbnail.type
原文件名: req.files.thumbnail.name

需要注意的是,默认的上传目录或你指定的上传目录都只是临时目录,因此你还需要将上传的文件移动相应的文件目录。下面的示例代码演示了如何将上传的文件移动到’/images’目录下:

   // 移动文件需要使用fs模块
   var fs = require('fs');
   app.post('/file-upload', function(req, res) {
     // 获得文件的临时路径
     var tmp_path = req.files.thumbnail.path;
    // 指定文件上传后的目录 - 示例为"images"目录。 
    var target_path = './public/images/' + req.files.thumbnail.name;
    // 移动文件
    fs.rename(tmp_path, target_path, function(err) {
      if (err) throw err;
      // 删除临时文件夹文件, 
      fs.unlink(tmp_path, function() {
         if (err) throw err;
         res.send('File uploaded to: ' + target_path + ' - ' + req.files.thumbnail.size + ' bytes');
      });
    });
  };

你可以将上传目录指定为任何你可以在当前操作系统环境下可以访问的目录。如果你希望这些文件可以被公开访问,你可以将文件拷贝到应用的静态目录’/public’下。需要注意的是,如果需要将文件拷贝到public或其子目录下,请确保文件夹存在,且可以被写入。否则会出现’Error: ENOENT, no such file’等异常信息。

现在在ExpressJS中上传文件将是一件非常简单的事情。如果你的原有应用需要使用文件上传,那么我建议你将应用升级到最新的ExpressJS框架,并且修改你的程序以保证功能可以正常工作。