关于自定义协议下载文件的问题
start函数是这么写的public void Start(string szURL, IInternetProtocolSink Sink, IInternetBindInfo pOIBindInfo, uint grfPI, uint dwReserved)
{
try 
{
              
if (Sink is IServiceProvider)
{
IServiceProvider Provider = (IServiceProvider)Sink;
                    pSink = Sink;
object obj_Negotiate = new object();
Provider.QueryService(ref Guids.IID_IHttpNegotiate, ref Guids.IID_IHttpNegotiate, out obj_Negotiate);
IHttpNegotiate Negotiate = (IHttpNegotiate)obj_Negotiate; string strNewHeaders;
Negotiate.BeginningTransaction(szURL, string.Empty, 0, out strNewHeaders); StreamWriter Writer = new StreamWriter(Stream);                    StreamBuffer = System.IO.File.ReadAllBytes(@"C:\1.mp3");                    string StrResponseHeaders = string.Format("HTTP/1.1 200 OK\r\nAccept-Ranges: bytes;\r\nContent-Type: application/octet-stream;\r\nContent-Length:{0}\r\n\r\n", StreamBuffer.Length);
string strNewResponseHeaders;
Negotiate.OnResponse(200, StrResponseHeaders, strNewHeaders, out strNewResponseHeaders);
Debug.WriteLine(strNewResponseHeaders);
}
                //向IE报告数据状态,但是文件下载的时候报告数据之后不会调用read方法
                Sink.ReportData(BSCF.BSCF_LASTDATANOTIFICATION, (uint)0, (uint)StreamBuffer.Length);
                Sink.ReportData(BSCF.BSCF_DATAFULLYAVAILABLE, (uint)0, (uint)StreamBuffer.Length);
        } 
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
read函数是如下: public UInt32 Read(System.IntPtr pv, uint cb, out uint pcbRead)
{
            pcbRead = (uint)Math.Min(cb, Stream.Length - alreadyRead);
pcbRead = (uint)Stream.Read(StreamBuffer, 0, (int)pcbRead);
            Marshal.Copy(StreamBuffer, 0, pv, (int)pcbRead);
            alreadyRead += (int)pcbRead;            UInt32 response = (UInt32)S_OK;;            if (alreadyRead >= Stream.Length)
            {
                response = (UInt32)S_FALSE;
            }            return response;
}
html中是这么写的:<a href="echo:1.mp3">1.mp3</a>
在IE中点击以上html的链接,根据调试start函数执行了,但是在调用了Sink.ReportData(BSCF.BSCF_LASTDATANOTIFICATION, (uint)0, (uint)StreamBuffer.Length);
Sink.ReportData(BSCF.BSCF_DATAFULLYAVAILABLE, (uint)0, (uint)StreamBuffer.Length);这两个函数之后。IE弹出了下载对话框,却同时弹出了提示说Internet Explorer无法下载的对话框。
而且我加在read函数里面的断点也没断到。
为什么啊?
求解,谢谢

解决方案 »

  1.   

    问题好像出在这两句:Sink.ReportData(BSCF.BSCF_LASTDATANOTIFICATION, (uint)0, (uint)StreamBuffer.Length);
    Sink.ReportData(BSCF.BSCF_DATAFULLYAVAILABLE, (uint)0, (uint)StreamBuffer.Length);使用BSCF中不同的枚举值,有不同的效果。应该怎么解释,求解
      

  2.   

    如果只加这一句的话,点击链接,屏幕一闪就没了Sink.ReportData(BSCF.BSCF_LASTDATANOTIFICATION, (uint)0, (uint)StreamBuffer.Length);
      

  3.   

    刚在搞这个问题,已经成功。
    因为播放媒体文件一般是要使用文件映射技术的。而你将文件写到内存中,将无法映射。需再将文件保存到IE缓存中,并告知UrlMon.dll缓存文件名可以利用,就可以正常下载了。
    以下是c++的代码,请自行翻译
    MIMEtypeStr是文件MIME类型名
    if (lstrcmpW(MIMEtypeStr,L"application/octet-stream")==0)
       {
    //pOIProtSink->Switch()
    char FName[512]; int ExtPos=m_url.ReverseFind('.');
    //MessageBox(0, m_url.Right(m_url.GetLength()-ExtPos-1),"ExTName",0);
    CreateUrlCacheEntry(m_url,CurFileSize,m_url.Right(m_url.GetLength()-ExtPos-1), FName, 0);
    FILE *file=fopen(FName,"w+b");
    fwrite(CurFileBuf,CurFileSize,1,file);
    fclose(file);
    USES_CONVERSION;
    m_spSink->ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE,A2W(FName));
    MessageBox(0,FName,"CacheFile_OK",0);
      
         }   pOIProtSink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, //已验证的MIME类型可以利用【很重要的一句】
     MIMEtypeStr);//根据文件内存获取MIME类型【对MIME filter 来说是必须的】
    以下再发送BSCF_FIRSTDATANOTIFICATION通知给UrlMon.dll
      

  4.   

    CurFileBuf指内存中文件的首地址
    CurFileSize指内存中文件的大小
    即你的StreamBuffer的相关成员