#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()
. Я последовал примеру данной ссылки и работал.