如何直接在云端上传图片而不将其存储到本地目录中?

Posted

技术标签:

【中文标题】如何直接在云端上传图片而不将其存储到本地目录中?【英文标题】:How to upload images directly on cloudinary without storing it into local directory? 【发布时间】:2021-03-27 20:46:02 【问题描述】:

我是 ExpressJs 的新手,正在为在 reactjs 中创建的仪表板之一创建 api。仪表板中有一个表单,它从用户那里收集一些信息,如“标题”、“描述”和“图像”。我创建了一个快速服务器来收集该信息并将其保存到 mongodb。对于图片我所做的是,我将图片上传到Cloudinary,并将上传的 url 和 public_id 存储到数据库中。

所以在学习了一些教程之后,我做了这样的事情。

index.js

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");

const db = require("./db");

// Api router import goes here
const sectionTypesRouter = require("./routes/section-types-router");

const app = express();
const apiPort = 3000;

app.use(bodyParser.urlencoded( extended: true ));
app.use(cors());
app.use(bodyParser.json());

db.on("error", console.error.bind(console, "MongoDB connection error:"));

app.get("/", (req, res) => 
  res.send("Hello World!");
);

app.use("/api", sectionTypesRouter);

app.listen(apiPort, () => console.log(`Server running on port $apiPort`));

比,首先我创建了一个文件 multer.js

const multer = require("multer");

const storage = multer.diskStorage(
  destination: "public/uploads",
  filename: (req, file, cb) => 
    cb(null, file.fieldname + "-" + Date.now());
  ,
);

const fileFilter = (req, file, cb) => 
  if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") 
    cb(null, true);
   else 
    //reject file
    cb( message: "Unsupported file format" , false);
  
;

const upload = multer(
  storage: storage,
  fileFilter: fileFilter,
);

module.exports = upload;

下面是我的api路由器section-type-router.js

const express = require("express");
const upload = require("../utils/multer");

const SectionTypesCtrl = require("../controllers/section-types-ctrl");

const router = express.Router();

router.post(
  "/section-type",
  upload.single("image"),
  SectionTypesCtrl.createSectionType
);
router.get("/section-types", SectionTypesCtrl.getSectionTypes);

module.exports = router;

这是 section-type-ctrl.js

const SectionType = require("../models/section-type-model");
const fs = require("fs");
const path = require("path");
const cloudinaryUploader = require("../utils/cloudinaryUploader");

const createSectionType = async (req, res) => 
  const body = req.body;

  if (!body) 
    return res.status(400).json(
      success: false,
      error: "Required parameter are missing",
    );
  
  cloudinaryUploader
    .uploads(req.file.path, "Section-Types")
    .then((result) => 
      const sectionType = new SectionType(
        title: body.title,
        description: body.description,
        image: 
          url: result.url,
          publicId: result.public_id,
        ,
      );
      sectionType
        .save()
        .then(() => 
          return res.status(201).json(
            success: true,
            id: sectionType._id,
            message: "Section type created!",
          );
        )
        .catch((error) => 
          return res.status(400).json(
            error,
            message: "Section type not created!",
          );
        );
    )
    .catch((error) => 
      res.status(500).send(
        message: "failure",
        error,
      );
    );
;

module.exports = 
  createSectionType,
;

最后是 cloudinaryUpload.js

const cloudinary = require("../config/cloudinary");

exports.uploads = (file, folder) => 
  return new Promise((resolve) => 
    cloudinary.uploader.upload(
      file,
      
        resource_type: "auto",
        folder: folder,
      ,
      (err, result) => 
        if (!err) 
          resolve(
            url: result.url,
            public_id: result.public_id,
          );
         else 
          throw err;
        
      
    );
  ).catch((error) => 
    throw error;
  );
;

现在,一切正常。图像上传到云端并返回 url,public_id 存储在数据库中。但问题是我上传的图片也上传到了本地目录public/uploads/。这可能会在托管站点时产生存储问题。那么有没有最好的方法可以直接将图像上传到云端而不在本地目录中创建副本,这也应该在生产模式下工作?

【问题讨论】:

有一个 npm 模块用于 multer npmjs.com/package/multer-storage-cloudinary 我也尝试用谷歌搜索“express.js cloudinary upload without storage file on local drive”并找到了足够的信息来帮助你做到这一点,也试试 google . 我们托管应用程序会好吗?我的意思是,如果直接上传而不存储到本地,您确定不会有问题吗?我还发现使用upload_stream 功能将图像上传为按钮。它会起作用吗? 【参考方案1】:

在您的示例中,文件被存储到您服务器上的 public/uploads,因为您通过 multer.diskStorage 告诉 multer 这样做

正如@Molda 上面的评论所说,您可以通过使用multer-storage-cloudinary 包让 Multer 自动将文件存储在 Cloudinary 中来避免这种情况。

另一种可能性是更改您使用 Multer 的方式,使其不会将文件存储在任何地方,然后在内存中获取上传的文件并将其作为流传递给 Cloudinary 的 SDK。

Cloudinary 网站上的这篇博文中有一个例子:https://cloudinary.com/blog/node_js_file_upload_to_a_local_server_or_to_the_cloud

在您的情况下,您可以停止使用multer.diskStorage,而只使用multer(),然后使用streamifier或其他库将上传的文件转换为流,并将其传递给cloudinary.uploader.upload_stream()

【讨论】:

谢谢。我使用cloudinary.uploader.upload_stream() 解决了。我已经按照给定链接的示例进行了操作。

以上是关于如何直接在云端上传图片而不将其存储到本地目录中?的主要内容,如果未能解决你的问题,请参考以下文章

如何流式传输从 FTP 获取的文件而不将其存储在本地?

捕获图像而不将其存储到内部/外部存储

在spring mvc中上传图片

将 python 对象上传到 Google Cloud Storage 而不将其保存到文件

如何直接保存到持久存储,而不将数据保存到内存中

下载然后上传图像而不存储它