火狐浏览器错误"Image contains errors and cannot be displayed"



我正在为 Mozilla Firefox 开发一个扩展,我用自己的扩展覆盖本机侦听器并监控所有 HTTP 请求,如这里的帖子所示: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,然后将其存储到流中。

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

相关内容

  • 没有找到相关文章

最新更新