在Mongo DB中存储数据url

9

我正在考虑将data-url存储在我的MongoDB中,而不是存储文件的引用或使用GridFS。

Data url

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMcAAAEsCAYAAAB38aczAAAgAElEQV

我存储的所有文件都是JPG或PNG格式,大小不超过1MB。

我想知道这是否被认为是不良实践,以及将 data-url 存储在 1)单独的集合中 2)作为元数据存储在集合中,对读写操作的性能影响如何。

如果有其他关于小文件存储的建议,我也很乐意听取。

2个回答

9
首先,我不建议在能够存储二进制数据的数据库中存储base64编码的数据,这只是浪费空间。应该存储图像本身,而不是它的base64表示,即不是data : "VBORw0KGgoAAAANSUhEUgAAA...",而是data : BinData("VBORw0KGgoAAAANSUhEUgAAA...")(前者是MongoDB的字符串,后者是二进制数据)。Base64会增加33%的大小。
除此之外,我认为这个方法还可以。权衡之后,选择一次请求获取所有数据还是多次请求获取数据。存储更大的数据块的缺点是需要将所有数据暂时保存在内存中,但对于1MB来说,这可能不是问题。
然而,你应该确保在不需要图像的情况下不要获取文档。1MB并不算太大,但对于读取频繁的集合来说,这是一个灾难。

谢谢。在我的情况下,很少需要抓取图像,并且对集合执行了几个读取密集型查询。我认为为所有现有查询指定排除是不明智的。因此,看起来我的选择是:1)只需将图像存储在我的文件服务器上,2)在单独的集合中存储二进制数据,创建引用,并使用mongoose的populate在必要时获取图像。 - TaylorMac
听起来分离集合最适合。我在一个个人项目中使用相同的概念,其中次要集合被称为... Images;-) 这很好用,对于这种使用模式,它比GridFS更好。 - mnemosyn
很高兴知道你用这种技术取得了成功。再次感谢mnemosyn分享的知识。 - TaylorMac

0
我刚刚完成了这个解决方案。这个解决方案使用Ajax,所以你可以在Javascript中使用fetch调用它。奇怪的是,在整个互联网上都找不到这个解决方案,这就是为什么我把它放在这里,帮助那些想要使用数据URI处理图像的人们 :-) 模型:
        cmsImage: { data: Buffer, contentType: String }

MongoDB中的存储:

        let rawData = fs.readFileSync(`${root}public/uploads/` + file.originalname);
        let base64Data = Buffer.from(rawData).toString('base64');

        // upload this image
        let image = { 
            cmsImage: {
                data: base64Data,
                contentType: file.mimetype
            }    
        };

        // in this record in the database
        await this.model.findByIdAndUpdate(body.id, image);        

从MongoDB中检索并动态创建图像元素:

       // decode image from database as image uri
       let imageArray = new Int8Array(image.data.data);
       let decodedImage = new TextDecoder().decode(imageArray);

       // image
       let cmsImage = document.createElement("img");
       cmsImage.src = "data:" + image.contentType + ";base64," + decodedImage;
       cmsImage.alt = "image";
       cmsContent.appendChild(cmsImage);

Multer - 使用原始文件进行上传到数据库。

      let storage = multer.diskStorage({
        destination: function (req, file, cb) {
          cb(null, './public/uploads')
        },
        filename: function (req, file, cb) {
          cb(null, file.originalname)
        }
      });

      this.upload = multer({ storage: storage });

上传至目录

      this.upload.single(uploadImage)

  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接