Transfer-Encoding:chunked 定义数据的包体部分为分块传输。
包体定义为:
-------------------------------------------------------------------------------------
16进制长度\r\n
内容区(字节)\r\n
16进制长度\r\n
内容区(字节)\r\n
0\r\n //标识分块结束,最后一块长度为0字节
\r\n //内容空行
\r\n //包体结束空行
-------------------------------------------------------------------------------------
实现如下:
/// <summary>
/// 以文件形式响应/// </summary>
/// <param name="httpContext">当前请求的上下文</param>
/// <param name="localfile">需要下载的文件</param>
/// <param name="fileName">下载后文件的名称,为空时,默认为 localfile 的文件名</param>
public static void DoResponseFile(HttpContext httpContext,string localfile,string fileName = null)
{
HttpResponse resp = httpContext.Response;
try
{
fileName = string.IsNullOrEmpty(fileName) ? FS.GetFileNameFromFilePathName(localfile) : fileName;
using (FileStream fs = File.OpenRead(localfile))
{
resp.ClearContent();
resp.ContentType = "application/octet-stream";
resp.AppendHeader("Content-Transfer-Encoding", "binary");
resp.Headers.Add("Content-Disposition", "attachment;filename=" + default2utf8string(httpContext, fileName));
resp.Headers.Add("Transfer-Encoding", "chunked");
byte[] bts = new byte[4096];
using (BinaryReader br = new BinaryReader(fs, System.Text.Encoding.UTF8))
{
int n = 0;
while ((n = br.Read(bts, 0, bts.Length)) > 0)
{
byte[] bbss = Encoding.UTF8.GetBytes(n.ToString("x") + "\r\n");
resp.OutputStream.Write(bbss, 0, bbss.Length);
resp.OutputStream.Write(bts, 0, n);
resp.OutputStream.Write(new byte[] { 13, 10 }, 0, 2);
resp.Flush();
}
byte[] bbss2 = Encoding.UTF8.GetBytes("0\r\n\r\n");
resp.OutputStream.Write(bbss2, 0, bbss2.Length);
}
}
}
catch (Exception ex)
{
resp.ClearContent();
resp.Write(ex);
}
resp.End();
}
private static string default2utf8string(HttpContext httpContext, string fileName)
{
string btype = httpContext.Request.Browser.Type.ToLower();
if (btype.IndexOf("firefox") >= 0)
{
byte[] bts = Encoding.UTF8.GetBytes(fileName);
return string.Format("=?UTF-8?B?{0}?=", Convert.ToBase64String(bts));
}
else
return httpContext.Server.UrlEncode(fileName);
}