关于自定义协议下载文件的问题
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函数里面的断点也没断到。
为什么啊?
求解,谢谢
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函数里面的断点也没断到。
为什么啊?
求解,谢谢
Sink.ReportData(BSCF.BSCF_DATAFULLYAVAILABLE, (uint)0, (uint)StreamBuffer.Length);使用BSCF中不同的枚举值,有不同的效果。应该怎么解释,求解
因为播放媒体文件一般是要使用文件映射技术的。而你将文件写到内存中,将无法映射。需再将文件保存到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
CurFileSize指内存中文件的大小
即你的StreamBuffer的相关成员