尝试使用 cloudinary 和 nodeJs 在产品中上传图片

Posted

技术标签:

【中文标题】尝试使用 cloudinary 和 nodeJs 在产品中上传图片【英文标题】:Try to upload image in product with cloudinary and nodeJs 【发布时间】:2021-09-02 07:38:30 【问题描述】:

我正在创建电子商务商店的后端,我必须验证照片。我从一个想法开始,但我的老师让我改变了,现在我不知道如何将我所做的与他对我的要求结合起来。让我解释一下情况:我创建了一个将图像上传到 cloudinary 的特殊路径。这是代码:

const router = require('express').Router()
const cloudinary = require('cloudinary')
const auth = require('./../middleware/auth')
const authAdmin = require('./../middleware/authAdmin')
const fs = require('fs-extra')


// we will upload image on cloudinary
cloudinary.config(
    cloud_name: process.env.CLOUD_NAME,
    api_key: process.env.CLOUD_API_KEY,
    api_secret: process.env.CLOUD_API_SECRET
)

// Upload image only admin can use
router.post('/upload', auth, authAdmin, (req, res) =>
    try 
        if(!req.files || Object.keys(req.files).length === 0)
            return res.status(400).json(msg: 'No files were uploaded.')
        
        const file = req.files.file;
        if(file.size > 1024*1024) 
            removeTmp(file.tempFilePath)
            return res.status(400).json(msg: "Size too large")
        

        if(file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png')
            removeTmp(file.tempFilePath)
            return res.status(400).json(msg: "File format is incorrect.")
        

        cloudinary.v2.uploader.upload(file.tempFilePath, folder: "ecommerce", async(err, result)=>
            if(err) throw err;

            removeTmp(file.tempFilePath)

            res.json(public_id: result.public_id, url: result.secure_url)
        )


     catch (err) 
        return res.status(500).json(msg: err.message)
    
)

// Delete image only admin can use
router.post('/destroy',auth , authAdmin, (req, res) =>
    try 
        const public_id = req.body;
        if(!public_id) return res.status(400).json(msg: 'No images Selected')

        cloudinary.v2.uploader.destroy(public_id, async(err, result) =>
            if(err) throw err;

            res.json(msg: "Deleted Image")
        )

     catch (err) 
        return res.status(500).json(msg: err.message)
    
    
)


const removeTmp = (path) =>
    fs.unlink(path, err=>
        if(err) throw err;
    )


module.exports = router

我有一个这样的产品模型:

const mongoose = require('mongoose')
const productSchema = new mongoose.Schema(
    name:
        type: String,
        trim: true,
        required: true
    ,
    price:
        type: Number,
        trim: true,
        required: true
    ,
    description:
        type: String,
        required: true
    ,
    images:
        type: Object,
        required: true
     
    ,
    category:
        type: mongoose.Schema.Types.ObjectId,
        ref: "Category",
        required: true
    ,
, 
    timestamps: true
)


module.exports = mongoose.model("Products", productSchema)

这是我创建产品的功能:

 createProduct: async (req, res) => 
        try 
            const 
                name,
                price,
                images,
                description,
                categoryId
             = req.body;
              
           

            if (!images) return res.status(400).json(
                message: "No hay imagen del producto!"
            )

            if (!(name || price || description))
                return res.status(400).json(
                    message: "Por favor, complete todos los campos"
                )

            const product = await Products.findOne(
                name
            )
            if (product)
                return res.status(400).json(
                    message: "Este producto ya ha sido creado anteriormente"
                )

            const newProduct = new Products(
                name: name.toLowerCase(),
                price,
                description,
                categoryId,
                images
            )

            await newProduct.save()
            res.json(
                message: "Producto creado ! "
            )

         catch (err) 
            return res.status(500).json(
                message: err.message
            )
        
    , 

这是创建产品的途径:

app.use('/api', require('./routes/productRouter'))
router.post('/products', auth, authAdmin, productCtrl.createProduct)

重点是,首先我要上传图片,在创建产品的时候,会通过Postman把图片上传的结果(public_id和url)传递出去。

在复习中,我的老师告诉我要把所有东西放在同一条路线上,即创造产品的路线上,我已经尝试了整个上午,但它对我没有任何作用。有人可以帮助我吗?我不知道集成图像的功能应该是什么样子。

诚挚的问候,提前谢谢你

【问题讨论】:

就在您创建产品调用时,您会路由(邮递员调用的同一个女巫)并创建图像,然后放置创建产品的其余代码。 我不知道怎么做,你能帮我看看这些代码吗?非常感谢 显示路线女巫创建图像的完整代码。你只放了功能代码,但我们不知道路线的路径。并发布您在邮递员中使用的请求女巫 我现在用所有代码编辑了这个问题 因为堆栈上的代码编辑器很烂 :( 我在sandbox 中提出了一些提示,您问题的关键是使用multer 包然后我将您的上传代码移动到单独的文件中,然后我promisificat 它. 在上传路径中我使用此代码并在创建产品中。所以在 createdProduc 的路径中我放置了 multer 上传中间件然后在请求中我们可以使用 body 和 files 数组。你可以在 cmets 中找到一些教程链接。我希望这个帮助你。 【参考方案1】:

// Create Product -- Admin
exports.createProduct = catchAsyncErrors(async (req, res, next) => 
  let images = [];

  if (typeof req.body.images === "string") 
    images.push(req.body.images);
   else 
    images = req.body.images;
  

  const imagesLinks = [];

  for (let i = 0; i < images.length; i++) 
    const result = await cloudinary.v2.uploader.upload(images[i], 
      folder: "products",
    );
    imagesLinks.push(
      public_id: result.public_id,
      url: result.secure_url,
    );
  

  req.body.images = imagesLinks;
  req.body.user = req.user.id;

  const product = await Product.create(req.body);
  res.status(201).json(
    success: true,
    product,
  );
);

【讨论】:

以上是关于尝试使用 cloudinary 和 nodeJs 在产品中上传图片的主要内容,如果未能解决你的问题,请参考以下文章

“路径”参数必须是字符串类型或 Buffer 或 URL cloudinary 和 nodejs 的实例

如何使用 nodejs 从 cloudinary 下载视频?

将图像上传到 Cloudinary

使用带有 cloudinary api 的 multer 库

Cloudinary 推荐用法

将不在我计算机上的图像上传到 Cloudinary