从二进制文件加载图像(Javascript-Ajax-MongoDB)

从二进制文件加载图像(Javascript-Ajax-MongoDB),javascript,image,mongodb,binary,Javascript,Image,Mongodb,Binary,我在MongoDB上保存了一个图像。模型如下所示: picture: { metadata: { name: { type: String, default: null }, comment: { type: String, default: null }, publisherID: { type: String,default: null }, date: { type: Date, default: Date.now }

我在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,但图像不显示。 (我不得不加入二进制数据,因为它们进入了一个数组)。
还有一些类似的帖子,但是它们没有我没有做过的任何事情(我想)。

如评论中所述,最好在应用程序中有一个单独的端点,使这些调用“看起来”像标准的静态文件请求。因此,I要做的第一件事是稍微更改您的模式:

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类型。因此,“path”是比
\u id
更“友好”的标识符,“mime类型”将在insert中设置以匹配返回的内容类型

然后设置一条路线来提供内容:

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 );
    }); 

})
所以当你提出这样的要求时:

这将发生:

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

  • 将“picture.mime”的文档属性指定为响应的内容类型

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

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


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

我真的不喜欢这种方法。最好有一个端点路由,它“似乎”是被请求图像的url。然后数据在响应中以二进制形式发送。这方面的浏览器缓存,而不是总是被要求这样做base64编码的方法将迫使。我真的不明白你的意思,你能详细一点吗?真的很好的人!非常感谢。不过,为了避免重复,我将坚持使用ID。@drakoumelitos或者您可以使“freindly”路径名受唯一索引约束。但是实现细节取决于最适合您的。没错,但我更愿意保持尽可能不友好的态度:D。无论如何,thnx很多!
  wget http://localhost:3000/images/test.png