2014-03-14 31 views
0

我有一個保存在MongoDB上的圖像。該模型如下:從二進制加載圖像(Javascript - Ajax - 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,但圖像顯示犯規的處理程序。 (我不得不加入二進制數據,因爲他們進入一個數組)。 還有一些其他類似的帖子,但他們沒有任何我沒有做過的(我認爲)。

+0

我真的不喜歡這種方法。最好有一個「出現」的端點路由作爲被請求映像的URL。然後,數據僅以二進制形式發送。這方面的瀏覽器緩存,而不是總是被要求,因爲這種base64編碼方法將強制。 –

+0

我真的不明白你的意思,你能詳細說明一下嗎? – Drakoumel

回答

1

正如評論中所述,它是更好有一個單獨的端點在您的應用程序中使這些調用「看起來像」標準的靜態文件請求。所以,第一件事會做的是改變你的架構一點:

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 
} 

因此,增加了兩個領域,其將要確定的「路徑」的形象相匹配,和「啞劇」的啞劇文件的類型。所以「路徑」是一個比_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’作爲內容類型的響應

  • 發送二進制數據作爲響應返回

所以對於客戶端來說,這是一個實際的文件作爲響應,重點是「瀏覽器」可以緩存這個和沒有命中你的應用程序的「緩存」副本是有效的。

如果您將Base64編碼的數據嵌入到JSON響應中,那麼您的寬鬆這個重要的部分,並且您每次發送數據。正如你發現的那樣,這也是一個非常混亂的過程。

+0

真的很好的人!非常感激。但是我會堅持使用ID以避免重複。 – Drakoumel

+0

@drakoumelitos或者你可以讓「freindly」路徑名受到唯一索引約束。但實現細節取決於最適合您的。 –

+0

是真實的,但我寧願保持儘可能不友好的狀態:D。無論如何thnx很多! – Drakoumel