首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GeckoFX文件下载

GeckoFX文件下载
EN

Stack Overflow用户
提问于 2017-06-02 21:10:32
回答 1查看 1.6K关注 0票数 1

我对GeckoFX文件的下载有一些问题。

我尝试了在一些位置描述的LauncherDialog方法,比如How to handle downloading in GeckoFX 29,以及WebRequest / Webclient方法。

这两种方法都可以工作,但它们对服务器执行两次请求。第一个将触发LauncherDialog.Download事件,LauncherDialog将发出一个新请求以获取实际文件。

我在客户端的自定义web客户机中使用GeckoFX,在这种情况下,这个下载请求需要服务器端几秒钟的处理,并修改数据状态。第二个请求被延迟,返回的数据与第一个请求的数据不一样。

而且,这个特定的应用程序不需要任何类型的下载进度窗口。

是否有任何方法从初始请求中获取数据流?修改不是问题。我更希望避免对GeckoFX进行任何修改,但如果需要,我会这样做的。

EN

回答 1

Stack Overflow用户

发布于 2017-06-03 18:40:07

嗯,我重新审视了我对XPCOM编程的错误假设,查看了Firefox/Gecko源代码中选定的位置,并找到了一个解决方案。对于具有XPCOM/XUL编程经验的人来说,这可能是非常明显的,但最初并不适合我。所以我想分享我的解决方案可以帮助一些人。

在我的例子中,LauncherDialog方法绝对不是要走的路。

相反,我实现了nsIFactorynsIExternalHelperAppServicensIStreamListener接口。

nsiStreamListener

代码语言:javascript
复制
internal class MyStreamListener : nsIStreamListener
{
    public MyStreamListener(/*...*/) { }
    public void OnStartRequest(nsIRequest aRequest, nsISupports aContext)
    {
        // This will get called once, when the download "begins".
        // You can initialize your things here.
    }

    public void OnStopRequest(nsIRequest aRequest, nsISupports aContext, int aStatusCode)
    {
        // This will also get called once, when the download is 
        // complete or interrupted. You can perform the post-download 
        // actions here.

        if (aStatusCode != GeckoError.NS_OK) {
            // download interrupted
        }
        else {
            // download completed
        }
    }

    public void OnDataAvailable(nsIRequest aRequest, nsISupports aContext, nsIInputStream aInputStream, ulong aOffset, uint aCount)
    {
        // This gets called several times with small chunks of data. 
        // Do what you need with the stream. In my case, I read it 
        // in a small buffer, which then gets written to an output 
        // filestream (not shown).
        // The aOffset parameter is the sum of all previously received data.

        var lInput = InputStream.Create(aInputStream);
        byte[] lBuffer = new byte[aCount];
        lInput.Read(lBuffer, 0, (int)aCount);

    }
}

nsIExternalHelperAppService

代码语言:javascript
复制
public class MyExternalHelperAppService : nsIExternalHelperAppService
{
     public MyExternalHelperAppService(/* ... */)
     {
        /* ... */
     }

     public nsIStreamListener DoContent(nsACStringBase aMimeContentType, nsIRequest aRequest, nsIInterfaceRequestor aWindowContext, bool aForceSave)
     {
         var request = Request.CreateRequest(aRequest);
         var lChannel = request as HttpChannel;
         try {
             if (lChannel != null) {
                 var uri = lChannel.OriginalUri;
                 var contentType = lChannel.ContentType;
                 var contentLength = lChannel.ContentLength;
                 var dispositionFilename = lChannel.ContentDispositionFilename;

                 // Do your contenttype validation, keeping only what you need.
                 // Make sure you clean dispositionFilename before using it.

                 // If you don't want to do anything with that file, you can return null;

                 return new MyStreamListener(/* ... */);
            }
        }
        catch (COMException) {
            /* ... */
        }
        return null;
    }
}

nsIFactory (您还可以重载GenericOneClassNsFactory):

代码语言:javascript
复制
public IntPtr CreateInstance(nsISupports aOuter, ref Guid iid)
{
    // This is called when the content dispatcher gets a DISPOSITION_ATTACHMENT 
    // on the channel, or when it doesn't have any builtin handler 
    // for the content type. It needs an external helper to handle 
    // the content, so it creates one and calls DoContent on it.

    MyExternalHelperAppService _myExternalHelperAppService = new MyExternalHelperAppService(...);
    IntPtr result;
    IntPtr iUnknownForObject = Marshal.GetIUnknownForObject(_myExternalHelperAppService);
    Marshal.QueryInterface(iUnknownForObject, ref iid, out result);
    Marshal.Release(iUnknownForObject);
    return result;
}

public void LockFactory(bool @lock) {
    // do nothing here, it's not used, only kept for backwards compatibility.
}

然后,在初始化代码的某个地方,我用适当的契约注册了我的nsIFactory

代码语言:javascript
复制
Xpcom.RegisterFactory(typeof(MyExternalHelperAppService).GUID,
    "MyExternalHelperAppService", 
    "@mozilla.org/uriloader/external-helper-app-service;1", 
    new MyNsFactory());

仅此而已。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44337489

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档