使用 Node.js、Express 和 Mongoose 上传图片

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5149545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 13:54:01  来源:igfitidea点击:

Uploading images using Node.js, Express, and Mongoose

node.jsimagefile-uploadexpressmongoose

提问by JohnAllen

Please consider newer answers that have more up-to-date information as things have changed over the years!

由于这些年来情况发生了变化,请考虑具有更多最新信息的较新答案!

Since many new Node.js libraries are quickly being rendered obsolete and there are relatively few examples anyways I want to ask about uploading images using:

由于许多新的 Node.js 库很快就会过时,而且示例相对较少,因此我想询问有关使用以下方法上传图像的问题:

  • Node.js (v0.4.1)
  • Express (1.0.7)
  • Mongoose (1.1.0).
  • Node.js (v0.4.1)
  • 快递 (1.0.7)
  • 猫鼬 (1.1.0)。

How have others done it?

其他人是如何做到的?

I've found: node-formidable, but I am new to uploading images in general so I want to learn general stuff and ways of doing so using Node.js and Express.

我发现:node-formidable,但我是一般上传图像的新手,所以我想学习一般的东西以及使用 Node.js 和 Express 这样做的方法。

回答by JohnAllen

I'll answer my own question for the first time. I found an example straight from the source. Please forgive the poor indentation. I wasn't sure how to indent properly when copying and pasting. The code comes straight from Express multipart/form-dataexampleon GitHub.

我将第一次回答我自己的问题。我直接从源代码中找到了一个示例。请原谅可怜的缩进。我不确定在复制和粘贴时如何正确缩进。代码直接来自GitHub 上的Expressmultipart/form-data示例

// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');

/**
 * Module dependencies.
 */

var express = require('../../lib/express')
  , form = require('connect-form');

var app = express.createServer(
  // connect-form (http://github.com/visionmedia/connect-form)
  // middleware uses the formidable middleware to parse urlencoded
  // and multipart form data
  form({ keepExtensions: true })
);

app.get('/', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Image: <input type="file" name="image" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});

app.post('/', function(req, res, next){

  // connect-form adds the req.form object
  // we can (optionally) define onComplete, passing
  // the exception (if any) fields parsed, and files parsed
  req.form.complete(function(err, fields, files){
    if (err) {
      next(err);
    } else {
      console.log('\nuploaded %s to %s'
        ,  files.image.filename
        , files.image.path);
      res.redirect('back');
    }
  });

  // We can add listeners for several form
  // events such as "progress"
  req.form.on('progress', function(bytesReceived, bytesExpected){
    var percent = (bytesReceived / bytesExpected * 100) | 0;
    process.stdout.write('Uploading: %' + percent + '\r');
  });
});

app.listen(3000);
console.log('Express app started on port 3000');

回答by Brent Faust

Since you're using express, just add bodyParser:

由于您使用的是 express,只需添加 bodyParser:

app.use(express.bodyParser());

then your route automatically has access to the uploaded file(s) in req.files:

那么你的路由会自动访问 req.files 中上传的文件:

app.post('/todo/create', function (req, res) {
    // TODO: move and rename the file using req.files.path & .name)
    res.send(console.dir(req.files));  // DEBUG: display available fields
});

If you name the input control "todo" like this (in Jade):

如果您像这样(在 Jade 中)将输入控件命名为“todo”:

form(action="/todo/create", method="POST", enctype="multipart/form-data")
    input(type='file', name='todo')
    button(type='submit') New

Then the uploaded file is ready by the time you get the path and original filename in 'files.todo':

然后,当您在“files.todo”中获取路径和原始文件名时,上传的文件已准备就绪:

  • req.files.todo.path, and
  • req.files.todo.name
  • req.files.todo.path,和
  • req.files.todo.name

other useful req.files properties:

其他有用的 req.files 属性:

  • size (in bytes)
  • type (e.g., 'image/png')
  • lastModifiedate
  • _writeStream.encoding (e.g, 'binary')
  • 大小(以字节为单位)
  • 类型(例如,'image/png')
  • 上次修改日期
  • _writeStream.encoding(例如,'二进制')

回答by srquinn

You can configure the connect body parser middleware in a configuration block in your main application file:

您可以在主应用程序文件的配置块中配置连接体解析器中间件:

    /** Form Handling */
    app.use(express.bodyParser({
        uploadDir: '/tmp/uploads',
        keepExtensions: true
    }))
    app.use(express.limit('5mb'));

回答by log N

See, the best thing you can do is to just upload the image to the disk and save the URL in MongoDB. Rest when you retrieve the image again. Just specify the URL, and you will get an image. The code for uploading is as follows.

看,您能做的最好的事情就是将图像上传到磁盘并将 URL 保存在 MongoDB 中。再次检索图像时休息。只需指定 URL,您将获得一个图像。上传代码如下。

app.post('/upload', function(req, res) {
    // Get the temporary location of the file
    var tmp_path = req.files.thumbnail.path;
    // Set where the file should actually exists - in this case it is in the "images" directory.
    target_path = '/tmp/' + req.files.thumbnail.name;
    // Move the file from the temporary location to the intended location
    fs.rename(tmp_path, target_path, function(err) {
        if (err)
            throw err;
        // Delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files.
        fs.unlink(tmp_path, function() {
            if (err)
                throw err;
            //
        });
    });
});

Now save the target path in your MongoDB database.

现在将目标路径保存在 MongoDB 数据库中。

Again, while retrieving the image, just extract the URL from the MongoDB database, and use it on this method.

同样,在检索图像时,只需从 MongoDB 数据库中提取 URL,并在此方法中使用它。

fs.readFile(target_path, "binary", function(error, file) {
    if(error) {
        res.writeHead(500, {"Content-Type": "text/plain"});
        res.write(error + "\n");
        res.end();
    }
    else {
        res.writeHead(200, {"Content-Type": "image/png"});
        res.write(file, "binary");
    }
});

回答by Dar Hamid

Try this code.It will help.

试试这个代码。它会有所帮助。

app.get('/photos/new', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Data: <input type="filename" name="filename" /></p>'
    + '<p>file: <input type="file" name="file" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});


 app.post('/photos/new', function(req, res) {
  req.form.complete(function(err, fields, files) {
    if(err) {
      next(err);
    } else {
      ins = fs.createReadStream(files.photo.path);
      ous = fs.createWriteStream(__dirname + '/directory were u want to store image/' + files.photo.filename);
      util.pump(ins, ous, function(err) {
        if(err) {
          next(err);
        } else {
          res.redirect('/photos');
        }
      });
      //console.log('\nUploaded %s to %s', files.photo.filename, files.photo.path);
      //res.send('Uploaded ' + files.photo.filename + ' to ' + files.photo.path);
    }
  });
});

if (!module.parent) {
  app.listen(8000);
  console.log("Express server listening on port %d, log on to http://127.0.0.1:8000", app.address().port);
}

回答by Manuela

You can also use the following to set a path where it saves the file.

您还可以使用以下内容来设置保存文件的路径。

req.form.uploadDir = "<path>";

回答by Jon J

I created an examplethat uses Express and Multer. It is very simple and avoids all Connectwarnings

创建了一个使用 Express 和 Multer 的示例。它非常简单并且避免了所有Connect警告

It might help somebody.

它可能会帮助某人。

回答by Squidinker

Again if you don't want to use bodyParser, the following works:

同样,如果您不想使用 bodyParser,则以下操作有效:

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

app.use(express.static('./public'));


app.configure(function(){
    app.use(express.methodOverride());
    app.use(express.multipart({
        uploadDir: './uploads',
        keepExtensions: true
    }));
});


app.use(app.router);

app.get('/upload', function(req, res){
    // Render page with upload form
    res.render('upload');
});

app.post('/upload', function(req, res){
    // Returns json of uploaded file
    res.json(req.files);
});

http.createServer(app).listen(3000, function() {
    console.log('App started');
});

回答by Risto Novik

For Express 3.0, if you want to use the formidable events, you must remove the multipart middleware, so you can create the new instance of it.

对于 Express 3.0,如果要使用强大的事件,则必须删除 multipart 中间件,以便创建它的新实例。

To do this:

去做这个:

app.use(express.bodyParser());

Can be written as:

可以写成:

app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart()); // Remove this line

And now create the form object:

现在创建表单对象:

exports.upload = function(req, res) {
    var form = new formidable.IncomingForm;
    form.keepExtensions = true;
    form.uploadDir = 'tmp/';

    form.parse(req, function(err, fields, files){
        if (err) return res.end('You found error');
        // Do something with files.image etc
        console.log(files.image);
    });

    form.on('progress', function(bytesReceived, bytesExpected) {
        console.log(bytesReceived + ' ' + bytesExpected);
    });

    form.on('error', function(err) {
        res.writeHead(400, {'content-type': 'text/plain'}); // 400: Bad Request
        res.end('error:\n\n'+util.inspect(err));
    });
    res.end('Done');
    return;
};

I have also posted this on my blog, Getting formidable form object in Express 3.0 on upload.

我也在我的博客上发布了这个,在 Express 3.0 上传时获取强大的表单对象

回答by GMeister

I know that the original question related to specific versions, but it also referred to the "latest" - @JohnAllen 's post is no longer relevant due to Expressjs bodyParser and connect-form

我知道原始问题与特定版本有关,但它也提到了“最新” - 由于Expressjs bodyParser 和 connect-form@JohnAllen的帖子不再相关

This demonstrates the easy to use in-built bodyParser():

这演示了易于使用的内置 bodyParser():

 /**
 * Module dependencies.
 */

var express = require('express')

var app = express()
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/home/svn/rest-api/uploaded' }))

app.get('/', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Image: <input type="file" name="image" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});

app.post('/', function(req, res, next){

    res.send('Uploaded: ' + req.files.image.name)
    return next()

});

app.listen(3000);
console.log('Express app started on port 3000');