How to find specific cache entries in firefox and turn them into a File or Blob object?

I have the following script:

User can embed html content in wysiwyg editor. When this pasted content contains images hosted in other domains, I want them to be uploaded to my server. Right now, the only way to do this is to manually upload via the context menu "save image as ...", and then upload the image to the server through the form and update the images in the editor.

I need to solve this client side.

I am working on a firefox addon that can automate the process. Of course, I could download these images, store them on my hard drive, and then upload them using FormData or better, but this seems awkward, since the content is displayed in the browser, it should already be loaded and be somewhere in memory. I would like to capture image files from memory and tell firefox to download them (maybe Blob is enough for them).

However, I am hopelessly lost in the API documentation for several different caching systems on MDN and cannot find any sample code for how to use them. I checked the code of other add-ons that access the cache, but most of them are without comment and are still quite mysterious.

Can you give me an example of how the recommended way would be to do this? The best solution would be if I can request a specific url from firefox so that I can use it in FormData, and if it is not in the firefox cache to load into memory, but if it is already there, I just get it directly.

+4
source share
1 answer

HTTP- Mozilla 2 . , , , - . , 100% - , , , . , Mozilla , API. , , .

. , , , , . , URI , . , .

, HTTP- , , , , . , , (, ) , . , ALWAYS , . , , ( - + - Mozilla) .

URI , , . . - nsICacheEntryOpenCallback. , . -: onCacheEntryCheck (, appcache) onCacheEntryAvilable (, isnew, appcache, ).

:

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 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 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-, . , .

, , !

+4

Source: https://habr.com/ru/post/1570469/


All Articles