【问题标题】:Load Image from Binary (Javascript - Ajax - MongoDB)从二进制加载图像(Javascript - Ajax - MongoDB)
【发布时间】:2014-04-19 04:30:40
【问题描述】:

我在 MongoDB 上保存了一张图片。模型如下:

picture: {
    metadata: {
        name: { type: String, default: null },
        comment: { type: String, default: null },
        publisherID: { type: String,default: null },
        date: { type: Date, default: Date.now },
        size: { type: Number,default: 0 },
        type: { type: String, default: null }
    },
    data: { type: Buffer, default: null },
    tags: Array
}

现在我需要再次从数据库加载图像。

我进行 AJAX 调用并请求带有 id 的图片。

        $.ajax({
        type: "POST",
        url: window.location.origin + '/picture',
        contentType: 'application/json',
        dataType: 'json',
        async: true,
        data: JSON.stringify({ id: id }),
        success: function (result) {
            console.log(result);
            a = result;

            var img = result.result[0].picture.data.join("").toString('base64');
            img = "data:" + result.result[0].picture.metadata.type + ";base64," + img;

            $('#img').attr('src', img);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log('error ' + textStatus + " " + errorThrown);
            success = false;
        }
    });

这是服务器上的处理程序

    var Picture = require('../models/picture');
Picture.find({ "_id": req.body.id}, function (err, pic) {
    if (err || !pic)
        res.end(JSON.stringify({ result: "error" }));

    if (pic) {
        console.log(pic);
        res.end(JSON.stringify({ result: pic }));
    }
})

我已将二进制数据转换为 base64,但图像不显示。 (我不得不加入二进制数据,因为它们进入了一个数组)。 还有一些其他类似的帖子,但是他们没有我没有做过的任何事情(我认为)。

【问题讨论】:

  • 我真的不喜欢这种方法。最好有一个“看起来”是被请求图像的 url 的端点路由。然后数据只是在响应中作为二进制发送。这方面是浏览器缓存而不是总是被请求,因为这种 base64 编码方法会强制执行。
  • 我不太明白你的意思,你能详细说明一下吗?

标签: javascript image mongodb binary


【解决方案1】:

如 cmets 中所述,更好在您的应用程序中有一个单独的端点,以使这些调用“看起来像”标准静态文件请求。所以要做的第一件事就是稍微改变你的架构:

picture: {
    metadata: {
        name: { type: String, default: null },
        comment: { type: String, default: null },
        publisherID: { type: String,default: null },
        date: { type: Date, default: Date.now },
        size: { type: Number,default: 0 },
        type: { type: String, default: null }
    },
    path: { type: String, required: true },
    mime: { type: String, required: true },
    data: { type: Buffer, default: null },
    tags: Array
}

因此添加了两个字段,它们将标识要匹配的图像的“路径”,以及“mime”作为文件的 mime 类型。所以“路径”是比_id 更“友好”的标识符,并且“mime-type”将在插入中设置以匹配返回的内容类型。

然后你设置一个路由来提供内容:

app.get('/images/:imgname', function(req,res) {

    Picture.find({ "picture.path": req.param("imgname") }, function(err,pic) {
        if (err) // checking here

        // Sending response        
        res.set('Content-Type', pic.mime);
        res.send( pic[0].picture.data );
    }); 

})

所以当你提出这样的请求时:

  wget http://localhost:3000/images/test.png

这会发生:

  • 为“test.png”找到匹配“路径”的文档

  • 将“picture.mime”的文档属性指定为响应的 Content-Type

  • 将二进制数据作为响应发回

所以对于客户端来说,它是一个作为响应的实际文件,关键是“浏览器”可以缓存这个并且不会命中您的应用程序,其中“缓存”副本有效。

如果您在 JSON 响应中嵌入 Base64 编码数据,那么您松开该重要部分并且您每次都发送数据。正如您所发现的,这也是一个非常混乱的处理过程。

【讨论】:

  • 真是个好人!非常感激。但是我会坚持使用 ID 以避免重复。
  • @drakoumelitos 或者您可以使“友好”路径名受制于唯一索引约束。但实施细节取决于最适合您的方式。
  • 确实如此,但我希望尽可能保持不友好:D。反正thnx很多!
猜你喜欢
  • 1970-01-01
  • 2012-11-28
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 2010-11-08
  • 2018-06-25
相关资源
最近更新 更多