首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用multer-storage-cloudinary包从Cloudinary中删除镜像?

如何使用multer-storage-cloudinary包从Cloudinary中删除镜像?
EN

Stack Overflow用户
提问于 2020-08-30 11:00:15
回答 3查看 544关注 0票数 1

我可以使用multer-storage-cloudinary包成功地上传镜像,但是我还没有拼凑出如何从我的更新或删除路径中销毁cloudinary中的镜像的实现。我找到的所有资源都只是参考上传图片。这是我上传图片所需的内容

代码语言:javascript
复制
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');
const multer = require('multer');

cloudinary.config({
  cloud_name: process.env.CLOUD_NAME,
  api_key: process.env.API_KEY,
  api_secret: process.env.API_SECRET
});

const storage = new CloudinaryStorage({
  cloudinary: cloudinary,
  params: {
    folder: "works",
    allowedFormats: ["jpg", "png"]
  }
});
const imgUpload = multer({ storage: storage });

router.post('/', withAuth, imgUpload.single('work-img'), (req, res) => {
  console.log(req.file);

  Post.create({
        title       : req.body.title,
        dimension   : req.body.dimensions,
        description : req.body.description,
        media       : req.body.media,
        img_url     : req.file.path,
        user_id     : req.session.user_id
    })
        .then((dbPostData) => res.json(dbPostData))
        .catch((err) => {
            console.log(err);
            res.status(500).json(err);
        });
});

下面是处理表单提交的前端代码

代码语言:javascript
复制
async function newFormHandler(event) {
    event.preventDefault();

    const form = document.querySelector('#new-post-form');

    const formData = new FormData(form);

    const response = await fetch(`/api/posts`, {
        method : 'POST',
        body   : formData
    });

    if (response.ok) {
        document.location.replace('/dashboard');
    } else {
        alert(response.statusText);
    }
}

document.querySelector('#new-post-form').addEventListener('submit', newFormHandler);

最后是我的更新路径,它上传一个新图像并将其新路径保存到数据库中,但我也想从Cloudinary中删除旧图像,这样我就不会在那里建立未使用的工件。

代码语言:javascript
复制
router.put('/:id', withAuth, imgUpload.single('work-img'), (req, res) => {
    Post.update(
        {
            title       : req.body.title,
            dimension   : req.body.dimensions,
            description : req.body.description,
            media       : req.body.media,
            img_url     : req.file.path
        },
        {
            where : {
                id : req.params.id
            }
        }
    )
        .then((dbPostData) => {
            if (!dbPostData) {
                res.status(404).json({ message: 'No post found with this id' });
                return;
            }
            res.json(dbPostData);
        })
        .catch((err) => {
      console.log(err);
            res.status(500).json(err);
        });
});

如果我查看post路由中的console.log(req.file),它会显示如下所示

代码语言:javascript
复制
{
  fieldname: 'work-img',
  originalname: '20171005_134508.jpg',
  encoding: '7bit',
  mimetype: 'image/jpeg',
  path: 'https://res.cloudinary.com/xxxxxxxxx/image/upload/xxxxxxxx/works/ujrrf13kyil8l5rjccwf.jpg',
  size: 3647252,
  filename: 'works/ujrrf13kyil8l5rjccwf'
}

根据Cloudinary API文档,响应看起来与"public_id“这样的键有很大不同。

代码语言:javascript
复制
{
  "public_id": "eneivicys42bq5f2jpn2",
  "version": 1570979139,
  "signature": "abcdefghijklmnopqrstuvwxyz12345",
  "width": 1000,
  "height": 672,
  "format": "jpg",
  "resource_type": "image",
  "created_at": "2017-08-11T12:24:32Z",
  "tags": [],
  "bytes": 350749,
  "type": "upload",
  "etag": "5297bd123ad4ddad723483c176e35f6e",
  "url": "http://res.cloudinary.com/demo/image/upload/v1570979139/eneivicys42bq5f2jpn2.jpg",
  "secure_url": "https://res.cloudinary.com/demo/image/upload/v1570979139/eneivicys42bq5f2jpn2.jpg",
  "original_filename": "sample",
  "eager": [
    { "transformation": "c_pad,h_300,w_400",
      "width": 400,
      "height": 300,
      "url": "http://res.cloudinary.com/demo/image/upload/c_pad,h_300,w_400/v1570979139/eneivicys42bq5f2jpn2.jpg",
      "secure_url": "https://res.cloudinary.com/demo/image/upload/c_pad,h_300,w_400/v1570979139/eneivicys42bq5f2jpn2.jpg" },

然后,我可以将' public_id‘与destroy方法一起使用,但我不能访问public_id来配置: cloudinary.v2.uploader.destroy(public_id,options,callback);

我不清楚如何实现这一点,或者是否可以使用multer-storage-cloudinary包

EN

回答 3

Stack Overflow用户

发布于 2020-09-08 05:32:11

因此,对于任何可能感兴趣的人来说,我最终这样做的方式如下所示

代码语言:javascript
复制
router.put('/:id', withAuth, imgUpload.single('work-img'), (req, res) => {
    // if there was a picture updated -- NOTE THIS TECHNIQUE IS NOT DRY, IS THERE A WAY TO REFACTOR?
    if (req.file) {
        // find old public_id for image so we can delete it from cloudinary before updating the db with new path
        Post.findOne(
            {
                where : {
                    id : req.params.id
                }
            },
            {
                attributes : [ 'title', 'public_id' ]
            }
        )
            .then((oldPostData) => {
                const oldPublicId = oldPostData.get({ plain: true });

                // remove old image from cloudinary db
                cloudinary.uploader.destroy(oldPublicId.public_id, (err) => {
                    console.log(err);
                    console.log(oldPublicId, ' deleted');
                });

                // not in cloudinary callback since deletion from cloudinary is not critical to UX
                Post.update(
                    {
                        title       : req.body.title,
                        artist_name : req.body.artist,
                        dimension   : req.body.dimensions,
                        description : req.body.description,
                        media       : req.body.media,
                        img_url     : req.file.path,
                        public_id   : req.file.filename
                    },
                    {
                        where : {
                            id : req.params.id
                        }
                    }
                ).then((newPostData) => {
                    if (!newPostData) {
                        res.status(404).json({ message: 'No post found with this id' });
                        return;
                    }

                    req.flash('success', 'Your work has been updated!');
                    res.json(newPostData);
                });
            })
            .catch((err) => {
                console.log(err);
                res.status(500).json(err);
            });
    // in the else i just added the post to the db without the image file.
    } else {...}

如上所述,public_id是用来访问cloudinary中的图像的。因此,multer-storage-cloudinary中间件负责从表单中获取图像并将其直接上传到cloudinary,然后将来自cloudinary的响应打包到req.file中,multer通常会将其添加到请求对象中。(显然,模式需要使用新的public_id字段进行更新)。在PUT回调中,查询post的db并获取旧的public_id。解析它并将其传递给cloudinay.uploader.destroy()方法。如果您的路由位于与imgUpload配置不同的文件中,则需要使用cloudinary。然后,你可以从cloudinary回调内部更新你的db,也可以不更新,因为它们不相互依赖,cloudinary操作对用户体验并不重要。

票数 1
EN

Stack Overflow用户

发布于 2020-09-01 07:34:55

对于删除,public_id是必需的。如果在使用multer-storage-cloudinary时没有在响应中获得public_id,您可以在上传时将其作为参数传递,这将是Cloudinary上的图像的名称。要删除图像,只需使用该public_id即可。或者,您可以使用cloudinary.uploader.upload函数,它将返回带有public_id和您在示例响应中提到的其他详细信息的JSON。

票数 0
EN

Stack Overflow用户

发布于 2021-10-28 17:44:49

代码语言:javascript
复制
import { v2 as cloudinary } from "cloudinary";
import express from "express";
const router = express.Router();

router.route("/delete-image").post(async (req, res, next) => {
    try {
        cloudinary.uploader.destroy(req.body.public_id, function (error, result) {
            res.status(200).send({ result, error });
        });
    } catch (error) {
        next(error);
    }
    // public_id: "folder_name/file_name" WITHOUT file extension
});

export default router;

我就是这么做的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63653564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档