Node.js 通过 REST API 发送图像

Posted

技术标签:

【中文标题】Node.js 通过 REST API 发送图像【英文标题】:Node.js to send images via REST API 【发布时间】:2017-05-22 08:03:04 【问题描述】:

我正在努力寻找这方面的材料

我有一个使用 mongoDB 的用 node.js 编写的 rest API。

我希望用户能够上传图片(个人资料图片)并将它们保存在服务器上(在 mongoDB 中)。

几个问题,我看到推荐使用GridFS,这是最好的解决方案吗?

如何发送这些文件?我见过 res.sendFile,但这又是最好的解决方案吗?

如果有人有任何材料可以链接我,我将不胜感激

谢谢

【问题讨论】:

你好,Mwild,你是怎么解决这个问题的?我也有同样的问题,谢谢 @MarcusMenezes 我最终决定使用外部对象存储系统,在本例中为 S3。将图像与数据库分开似乎是一种更简洁的解决方案。我使用 busboy 来处理服务器端的图像。有关这方面的信息,请参阅下面汤姆的回答。 感谢您的回答! @mwild 【参考方案1】:

此外,这对于 AWS S3 或 Azure blob 存储等共享对象存储来说也是一个很好的案例。如果您在 AWS 之类的平台上运行分布式设置,您通常不希望将照片存储在本地服务器上。

将 url 或键名存储在指向 S3 对象的数据库中。这也很容易与 CloudFront CDN 集成。

如前所述。 MultiPart 用于实际上传。

【讨论】:

【参考方案2】:

您将无法直接在服务器上获取文件对象。要在服务器上获取文件对象,请使用 connect-multiparty 中间件。这将允许您访问服务器上的文件。

var multipart = require('connect-multiparty');
var multipartmiddleware = multipart();
var mv = require('mv');
var path = require('path');

app.post("/URL",multipartmiddleware,function(req,res)
    var uploadedImage = req.files.file;
    for (var i = 0; i < uploadedImage.length; i++) 
        var tempPath = uploadedImage[i].path;
        var targetPath = path.join(__dirname ,"../../../img/Ads/" + i + uploadedImage[i].name);

        mv(tempPath, targetPath, function (err) 
           if (err)  throw err; 
        );
    
)

【讨论】:

【参考方案3】:

如果您使用mongoose odm,您可以使用mongoose-crate 模块并将文件发送到任何地方进行存储。

【讨论】:

【参考方案4】:

使用文件系统

通常在任何数据库中,您将图像位置字符串的形式存储在数据中,告诉应用程序图像在文件系统中的存储位置强>。

除非您的数据库需要作为单个单元进行移植,否则将图像作为二进制对象存储在数据库内部通常会为您的数据库增加不必要的大小和复杂性。 -Michael Stearne

在 MongoDB 中,使用 GridFS 存储大于 16 MB 的文件。 - Mongo Documentation

因此,除非您的图像超过 16 MB,否则您应该将文件存储在 CDN(最好)或服务器自己的文件系统中,并将其 URL 保存到数据库中的用户文档。


本地文件系统实现

此方法使用Busboy解析上传的照片。

在相关的html文件中:

<input type="file" title="Choose a file to upload" accept="image/*" autofocus="1">

服务器文件中照片上传路由的处理函数(您需要填写适用于您的变量并需要必要的模块):

function photoUploadHandlerFunction (req, res) 
  var busboy = new Busboy( headers: req.headers )
  busboy.on('file', function (fieldname, file, filename, encoding, mimetype) 
    const saveToDir = path.join(__dirname, uploadsPath, user.id)
    const saveToFile = path.join(saveToDir, filename)
    const pathToFile = path.join(uploadsPath, user.id, filename)
    const writeStream = fs.createWriteStream(saveToFile)

    createDirIfNotExist(saveToDir)
      .then(pipeUploadToDisk(file, writeStream))
      .then(findUserAndUpdateProfilePic(user, pathToFile))
      .catch((err) => 
        res.writeHead(500)
        res.end(`Server broke its promise $err`)
      )
  )

  busboy.on('finish', function () 
    res.writeHead(200,  'Connection': 'close' )
    res.end("That's all folks!")
  )

  return req.pipe(busboy)

promise 函数 createDirIfNotExistpipeUploadToDisk 可能如下所示:

function createDirIfNotExist (directory, callback) 
  return new Promise(function (resolve, reject) 
    fs.stat(directory, function (err, stats) 
      // Check if error defined and the error code is "not exists"
      if (err) 
        if (err.code === 'ENOENT') 
          fs.mkdir(directory, (err) => 
            if (err) reject(err)
            resolve('made folder')
          )
         else 
          // just in case there was a different error:
          reject(err)
        
       else 
        resolve('folder already existed')
      
    )
  )


function pipeUploadToDisk (file, writeStream) 
  return new Promise((resolve, reject) => 
    const fileWriteStream = file.pipe(writeStream)
    fileWriteStream.on('finish', function () 
      resolve('file written to file system')
    )
    fileWriteStream.on('error', function () 
      reject('write to file system failed')
    )
  )


要回答您的问题“我如何发送这些文件?”,我需要知道去哪里(MongoDB,到客户端......)。如果您的意思是对客户,您可以提供保存它们的静态文件夹。

如果您仍想了解如何实施 GridFs 教程点,请联系good tutorial


更多材料

handling form uploads上的好教程 Tutorial 使用 node-formidable module

【讨论】:

以上是关于Node.js 通过 REST API 发送图像的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MobileFirst Foundation 8 中使用 REST API 从 Node.js 发送推送通知?

Node js中向rest服务发送https请求的步骤

Node js中向rest服务发送https请求的步骤

编写 Node.js Rest API 的 10 个最佳实践

nodejs使用Node.js实现REST Client调用REST API

Node.js REST API 从 MongoDB 获取数据