如何在cloudinary上直接上传图片而不存储到本地目录?
How to upload images directly on cloudinary without storing it into local directory?
我是 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;
});
};
现在,一切正常。图像正在上传到 cloudinary 并返回 url 并且 public_id 存储在数据库中。但问题是我上传的 图片也在本地目录 public/uploads/ 上上传。这可能会在托管网站时产生存储问题。那么有什么最好的方法可以将图像直接上传到 cloudinary 而无需在本地目录中创建副本,这也应该适用于生产模式?
在您的示例中,文件正在存储到您服务器上的 public/uploads
,因为您通过 multer.diskStorage
告诉 multer 这样做
正如上面@Molda 的评论所说,您可以通过使用 multer-storage-cloudinary
包让 Multer 自动将文件存储在 Cloudinary 中来避免这种情况。
另一种可能性是更改您使用 Multer 的方式,使其不会将文件存储在任何地方,然后在上传的文件在内存中时将其作为流传递给 Cloudinary 的 SDK。
Cloudinary 网站上的博客 post 中有一个这样的示例:https://cloudinary.com/blog/node_js_file_upload_to_a_local_server_or_to_the_cloud
在您的情况下,您可以停止使用 multer.diskStorage
,转而使用 multer()
,然后使用 streamifier 或其他库将上传的文件转换为流,并将其传递给 cloudinary.uploader.upload_stream()
我是 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;
});
};
现在,一切正常。图像正在上传到 cloudinary 并返回 url 并且 public_id 存储在数据库中。但问题是我上传的 图片也在本地目录 public/uploads/ 上上传。这可能会在托管网站时产生存储问题。那么有什么最好的方法可以将图像直接上传到 cloudinary 而无需在本地目录中创建副本,这也应该适用于生产模式?
在您的示例中,文件正在存储到您服务器上的 public/uploads
,因为您通过 multer.diskStorage
正如上面@Molda 的评论所说,您可以通过使用 multer-storage-cloudinary
包让 Multer 自动将文件存储在 Cloudinary 中来避免这种情况。
另一种可能性是更改您使用 Multer 的方式,使其不会将文件存储在任何地方,然后在上传的文件在内存中时将其作为流传递给 Cloudinary 的 SDK。
Cloudinary 网站上的博客 post 中有一个这样的示例:https://cloudinary.com/blog/node_js_file_upload_to_a_local_server_or_to_the_cloud
在您的情况下,您可以停止使用 multer.diskStorage
,转而使用 multer()
,然后使用 streamifier 或其他库将上传的文件转换为流,并将其传递给 cloudinary.uploader.upload_stream()