Firefox SDK 错误 "Image contains errors and cannot be displayed"

Firefox SDK Error "Image contains errors and cannot be displayed"

我正在为 Mozilla Firefox 开发一个扩展,我在其中用我自己的覆盖本机侦听器并监视所有 HTTP 请求,如 post 此处所示: http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/

我监视驻留在特定域下的那些请求,并使用我从自己的 XMLHTTPRequest 收到的响应主体更改它们相应的响应主体。对于文本文件,一切正常。

但是,我在下载图片时遇到了问题。出于某种原因,当我将传入数据写入流然后尝试打开图像时,出现图像包含错误且无法显示的错误。

我可能做错了什么?

更新: 我提供了一些代码,以阐明我的方法。



    var xmlRequest = Cc['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Ci.nsIXMLHttpRequest);
    ...
    xmlRequest.open('GET', xmlRequestURL, false);
    xmlRequest.send(null);

    function TracingListener() {}

    TracingListener.prototype = {
      originalListener: null,

      onStartRequest: function (request, context) {
        httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
        requestURL = httpChannel.URI.spec;

        try {
          this.originalListener.onStartRequest(request, context);
        } 
        catch (ex) {
          request.cancel(ex);
        }
      },

      onDataAvailable: function (request, context, inputStream, offset, count) {
        httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
        requestURL = httpChannel.URI.spec;

        //Read the contents from the stream, but ignore them.
        var binaryInputStream = CCIN('@mozilla.org/binaryinputstream;1', 'nsIBinaryInputStream');
        binaryInputStream.setInputStream(inputStream);

        var binaryOutputStream = CCIN('@mozilla.org/binaryoutputstream;1', 'nsIBinaryOutputStream');
        var data = binaryInputStream.readBytes(count);

        //Delay the call to the original listener.
      },

      onStopRequest: function (request, context, statusCode) {
        httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
        requestURL = httpChannel.URI.spec;

        //Check if the response is successful.
        if(xmlRequest.status == 200) {
          try {
            var responseLen = xmlRequest.getResponseHeader("Content-Length");
            var response = xmlRequest.response;

            var storageStream = CCIN('@mozilla.org/storagestream;1', 'nsIStorageStream');
            storageStream.init(8192, responseLen, null);

            var binaryOutputStream = CCIN('@mozilla.org/binaryoutputstream;1', 'nsIBinaryOutputStream');
            binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));

            binaryOutputStream.writeBytes(response, responseLen);

            //Make the call to the original listener.
            this.originalListener.onDataAvailable(request, context, storageStream.newInputStream(0), 0, responseLen);
          }
          catch (e) {
            dumpError(e);
          }

          //Pass it to the original listener
          this.originalListener.onStopRequest(request, context, statusCode);
        }
        else {
          console.log('[INFO] onStopRequest not processed, status is ' + xmlRequest.status + ', for URL: ' + requestURL);
        }
      }
    }

    var observer = {
      httpRequestObserver: {
        observe: function (request, aTopic, aData) {
          httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
          requestURL = httpChannel.URI.spec;

          if(mustBeMonitored(requestURL)) {
            console.log('[INFO] Observing URL: ' + requestURL);

            if (aTopic == 'http-on-modify-request') {
              console.log('[INFO] ' + aTopic + ' for URL: ' + requestURL);

              var newListener = new TracingListener();
              request.QueryInterface(Ci.nsITraceableChannel);
              newListener.originalListener = request.setNewListener(newListener);
            }
          }
        },

        register: function () {
          observerService.addObserver(observer.httpRequestObserver, 'http-on-modify-request', false);
        },
        unregister: function () {
          observerService.removeObserver(observer.httpRequestObserver, 'http-on-modify-request');
        },

        QueryInterface: function (aIID) {
          /*if (typeof Cc == "undefined") {
             var Cc = components.classes;
          }
          if (typeof Ci == "undefined") {
             var Ci = components.interfaces;
          }*/

          if (aIID.equals(Ci.nsIObserver) || aIID.equals(Ci.nsISupports))
             return this;
          throw components.results.NS_NOINTERFACE;
        }
      }
    };


终于,我发现了问题所在。对于 XMLHttpRequest,我必须按如下方式指定其响应类型:

xmlRequest.responseType = 'arraybuffer';

然后,响应存储在 JavaScript ArrayBuffer 中,我必须将其转换为 Uint8Array,然后将其存储到流中。

此解决方案适用于二进制文件和文本文件。