Как загружать изображения непосредственно в cloudinary, не сохраняя их в локальном каталоге?

#node.js #reactjs #express #multer #cloudinary

#node.js #reactjs #экспресс #мультер #cloudinary

Вопрос:

Я новичок в ExpressJS и работаю над созданием api для одной из панелей мониторинга, созданных в reactjs. На панели инструментов есть форма, которая собирает некоторую информацию от пользователей, такую как «заголовок», «описание» и «изображение». Я создал экспресс-сервер для сбора этой информации и сохранения ее в 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;
  });
};
 

Теперь все работает правильно. Изображения загружаются в cloudinary и возвращаются URL, а public_id сохраняется в базе данных. Но проблема в том, что загруженное мной изображение также загружается в локальный каталог public/uploads/ . Это может создать проблему с хранилищем при размещении сайта. Итак, есть ли лучший способ загрузить изображение непосредственно в cloudinary без создания копии в локальном каталоге, которая также должна работать в рабочем режиме?

Комментарии:

1. Для multer есть модуль npm npmjs.com/package/multer-storage-cloudinary также я попробовал погуглить «express.js загрузка в облако без сохранения файла на локальном диске» и нашел достаточно информации, которая должна помочь вам в этом, попробуйте также Google.

2. Будет ли это хорошо, пока мы размещаем приложение? Я имею в виду, вы уверены, что не будет проблем, если загружать напрямую, не сохраняя его локально? Я также нашел для загрузки изображения как кнопки с upload_stream функцией. Будет ли это работать?

Ответ №1:

В вашем примере файл сохраняется public/uploads на вашем сервере, потому что вы указываете multer сделать это через multer.diskStorage

Как говорится в комментарии @Molda выше, вы можете избежать этого, используя multer-storage-cloudinary пакет, чтобы Multer автоматически сохранял файл в Cloudinary.

Другая возможность — изменить способ использования Multer, чтобы он нигде не сохранял файл, затем возьмите загруженный файл, пока он находится в памяти, и передайте его в SDK Cloudinary в виде потока.

Пример этого приведен в этом сообщении в блоге на сайте 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()

Комментарии:

1. Спасибо. Я решил с помощью cloudinary.uploader.upload_stream() . Я последовал примеру данной ссылки и работал.