Mozilla版本2 HTTP緩存的主文檔位於here。除了這個頁面上的模糊之外,我能夠理解這個新方案的唯一方法是通過查看每個對象的實際代碼並反向引用幾乎所有的東西。儘管我無法清楚地瞭解到底發生了什麼,但我足夠了解它的工作原理。在我看來,Mozilla應該花時間在繼續推出新API之前創建一些簡單條款的文檔。但是,我們可以得到他們給我們的東西。
解決您的問題。我們假設想要上傳圖片的用戶已將此圖片保存在緩存中的某處。爲了能夠將其從用戶的緩存中取出用於上載,必須先能夠確定圖像的URI,然後才能從緩存中明確提取圖像的URI。爲了簡潔起見,我假設你已經找到了這個部分。
有關新HTTP緩存的一個重要事項是,儘管它都基於回調,但仍然只能有一個單獨的寫入過程。儘管在您的示例中可能不需要寫入描述符,但您仍然可以請求寫入權限,因爲這會阻止任何其他進程(即瀏覽器)在完成之前更改/刪除數據。另一個方面的說明和對我來說很痛苦的一個原因是,從內存緩存請求緩存條目將始終總是創建一個新條目,覆蓋任何預先存在的條目。你不應該需要這個,但是如果有必要的話,你可以從磁盤訪問內存緩存(磁盤緩存是物理磁盤+內存緩存 - Mozilla邏輯)緩存,沒有這種副作用。
一旦掌握了URI,就可以發出請求將其從緩存中取出。新的緩存系統完全基於回調。爲了能夠獲取緩存條目的數據,我們需要一個關鍵對象 - nsICacheEntryOpenCallback。這是一個用戶定義的對象,用於在請求緩存條目後處理響應。它必須有兩個成員函數:onCacheEntryCheck(entry,appcache)和onCacheEntryAvilable(描述符,isnew,appcache,status)。
這裏是我的這種對象的代碼刪節例如:
var cacheWaiter = {
//This function essentially tells the cache service whether or not we want
//this cache descriptor. If ENTRY_WANTED is returned, the cache descriptor is
//passed to onCacheEntryAvailable()
onCacheEntryCheck: function(descriptor, appcache)
{
//First, we want to be sure the cache entry is not currently being written
//so that we can be sure that the file is complete when we go to open it.
//If predictedDataSize > dataSize, chances are it's still in the process of
//being cached and we won't be able to get an exclusive lock on it and it
//will be incomplete, so we don't want it right now.
try{
if(descriptor.dataSize < descriptor.predictedDataSize)
//This tells the nsICacheService to call this function again once the
//currently writing process is done writing the cache entry.
return Components.interfaces.nsICacheEntryOpenCallback.RECHECK_AFTER_WRITE_FINISHED;
}
catch(e){
//Also return the same value for any other error
return Components.interfaces.nsICacheEntryOpenCallback.RECHECK_AFTER_WRITE_FINISHED;
}
//If no exceptions occurred and predictedDataSize == dataSize, tell the
//nsICacheService to pass the descriptor to this.onCacheEntryAvailable()
return Components.interfaces.nsICacheEntryOpenCallback.ENTRY_WANTED;
}
//Once we are certain we want to use this descriptor (i.e. it is done
//downloading and we want to read it), it gets passed to this function
//where we can do what we wish with it.
//At this point we will have full control of the descriptor until this
//function exits (or, I believe that's how it works)
onCacheEntryAvailable: function(descriptor, isnew, appcache, status)
{
//In this function, you can do your cache descriptor reads and store
//it in a Blob() for upload. I haven't actually tested the code I put
//here, modifications may be needed.
var cacheentryinputstream = descriptor.openInputStream(0);
var blobarray = new Array(0);
var buffer = new Array(1024);
for(var i = descriptor.dataSize; i > 0; i -= 1024)
{
try{
cacheentryinputstream.read(buffer, 1024);
}
catch(e){
//Nasty NS_ERROR_WOULD_BLOCK exceptions seem to happen to me
//frequently. The Mozilla guys don't provide a way around this,
//since they want a responsive UI at all costs. So, just keep
//trying until it succeeds.
i += 1024;
}
for(var j = 0; j < 1024; j++)
{
blobarray.push(buffer.charAt(j));
}
}
}
var theblob = new Blob(blobarray);
//Do an AJAX POST request here.
}
現在回調對象設置,我們實際上可以做緩存描述一些請求。嘗試是這樣的:
var theuri = "http://www.example.com/image.jpg";
//Load the cache service
var cacheservice = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"].getService(Components.interfaces.nsICacheStorageService);
//Load context info about the various caches
var {LoadContextInfo} = Components.utils.import("resource://gre/modules/LoadContextInfo.jsm",{})
//Select the default disk cache.
var hdcache = cacheservice.diskCacheStorage(LoadContextInfo.default, true);
//Request a cache entry for the URI. OPEN_NORMALLY requests write access.
hdcache.asyncOpenURI(ioservice.newURI(theuri, null, null), "", hdcache.OPEN_NORMALLY, cacheWaiter);
至於實際得到的URI,你可以爲用戶拖動和刪除一個圖像到或者只是圖像的URL粘貼到提供一個窗口。然後,您可以執行AJAX請求來獲取圖像(如果用戶由於某種原因未實際訪問該圖像,則會被緩存)。然後,您可以使用該URL來獲取上傳的緩存條目。作爲一種美感,你甚至可以展示圖像的預覽,但這有點超出了問題的範圍。
如果您需要更多的說明,請隨時詢問!
這位用戶在mozillazine,Githlar上,有很多緩存經驗,如果我有任何問題緩存相關,他告訴我由他來運行它。在mzine上發佈這個話題,併發送給這個人一條消息,這是一個很棒的問題,我希望看到一個答案:) – Noitidart
感謝您的提示,我支持tor防火牆,我無法訪問mozilla zine論壇,因爲它說ip禁止...你有任何聯繫這個用戶的方式嗎? – nus
你好nus,我有幾個問題:你所見即所得的編輯器就像一個web應用程序,對嗎?如果是這樣的話,你不需要插件來做到這一點,只需要一些服務器端腳本下載圖像,把它們放在某個地方,並用本地URL替換遠程URL的所有實例。但是,如果您必須使用擴展名......那麼我仍然試圖通過這個擴展。我可以告訴你,與我正在嘗試做的事情相比,這將是相當容易的。但我同意,Mozilla的Cache v2文檔非常糟糕。 –