.net网站的文件上传读取进度条和断点下载
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.net网站的文件上传读取进度条和断点下载相关的知识,希望对你有一定的参考价值。
文件上传到服务器时的进度读取
UpfileResult result = new UpfileResult(); try { //先把文件预读到内存里,同时计算上传进度 IServiceProvider provider = (IServiceProvider)HttpContext.Current; // 返回 HTTP 请求正文已被读取的部分。 HttpWorkerRequest request = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest)); // 获取上传大小 long length = long.Parse(request.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength)); CheckFileSize(length, info); int bytesRead = 0; // 已读数据大小 int read; // 当前读取的块的大小 int count = 8192; // 分块大小 byte[] buffer; // 保存所有上传的数据 byte[] tempBuff = null; if (request != null) { tempBuff = request.GetPreloadedEntityBody(); } if (tempBuff != null) { buffer = new byte[length]; // 分块大小 count = tempBuff.Length; // 将已上传数据复制过去 Buffer.BlockCopy(tempBuff, 0, buffer, bytesRead, count); // 开始记录已上传大小 bytesRead = tempBuff.Length; //计算当前上传文件的百分比 long percent = bytesRead * 100 / length; SetPercent(SessionId, percent); int ii = 0; // 循环分块读取,直到所有数据读取结束 while (request.IsClientConnected() && !request.IsEntireEntityBodyIsPreloaded() && bytesRead < length) { // 如果最后一块大小小于分块大小,则重新分块 if (bytesRead + count > length) { count = (int)(length - bytesRead); tempBuff = new byte[count]; } // 分块读取 read = request.ReadEntityBody(tempBuff, count); // 复制已读数据块 Buffer.BlockCopy(tempBuff, 0, buffer, bytesRead, read); // 记录已上传大小 bytesRead += read; ii++; if (ii % 10 == 0) { //计算当前上传文件的百分比 percent = bytesRead * 100 / length; SetPercent(SessionId, percent); } if (read == 0) { //如果前面读取过文件(Global.asax中的360验证),这里就读不到数据,需避免进入死循环 break; } } if (request.IsClientConnected() && !request.IsEntireEntityBodyIsPreloaded()) { // 传入已上传完的数据 // BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic; Type type = request.GetType(); while ((type != null) && (type.FullName != "System.Web.Hosting.ISAPIWorkerRequest")) { type = type.BaseType; } if (type != null) { type.GetField("_contentAvailLength", bindingFlags).SetValue(request, buffer.Length); type.GetField("_contentTotalLength", bindingFlags).SetValue(request, buffer.Length); type.GetField("_preloadedContent", bindingFlags).SetValue(request, buffer); type.GetField("_preloadedContentRead", bindingFlags).SetValue(request, true); } // 表示上传已结束 } } HttpPostedFile imgFile = _request.Files[0]; string fileName = imgFile.FileName; UpLoadFile(result, imgFile, fileName, info, SessionId); SetPercent(SessionId, 100); return result; } catch (Exception ex) { result.IsOk = false; result.ErrMsg = ex.Message; return result; }
服务器文件的断点下载
/// <summary> /// 支持断点下载 /// </summary> /// <param name="Request"></param> /// <param name="Response"></param> /// <param name="filePath">文件的物理地址</param> private void Down(HttpRequest Request, HttpResponse Response, string filePath) { /*断点下载与普通模式不一样的是: 断点下载的请求头信息里面增加一个属性 RANGE: bytes=100000- 响应头里 增加一个属性 Content-Range=bytes 100000-19999/20000 返回状态码为206(Partial Content) 表示头500个字节:Range: bytes=0-499 表示第二个500字节:Range: bytes=500-999 表示最后500个字节:Range: bytes=-500 表示500字节以后的范围:Range: bytes=500- 第一个和最后一个字节:Range: bytes=0-0,-1 同时指定几个范围:Range: bytes=500-600,601-999 */ // 打开文件 using (Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { // 获取文件的大小 long fileSize = fileStream.Length; string range = Request.Headers["Range"]; Response.Clear(); Response.AddHeader("Accept-Ranges", "bytes"); Response.AddHeader("Connection", "Keep-Alive"); Response.Buffer = false; //数据包大小 int pack = 10240; //10Kb int sleep = 0; if(this.Speed.HasValue) { sleep = (int)Math.Floor(1000.0 * 10 / this.Speed.Value); } long begin = 0; long end = fileSize - 1; if (!string.IsNullOrEmpty(range)) { //获取请求的范围,如果有多个范围,暂时只处理第一个,Range: bytes=500-600,601-999 range = range.Replace("bytes=", ""); range = range.Split(‘,‘)[0]; string[] region = range.Split(‘-‘); string startPoint = region[0].Trim(); string endPoint = region[1].Trim(); if (startPoint == "") { long.TryParse(endPoint, out end); begin = fileSize - end; end = fileSize - 1; } else if (endPoint == "") { long.TryParse(startPoint, out begin); end = fileSize - 1; } else { long.TryParse(startPoint, out begin); long.TryParse(endPoint, out end); } Response.StatusCode = 206; Response.AddHeader("Content-Range", string.Format("bytes {0}-{1}/{2}", begin, end, fileSize)); } //以字节流返回数据 Response.ContentType = "application/octet-stream"; //Response.ContentEncoding = System.Text.Encoding.UTF8; Response.AddHeader("Content-Disposition", "attachment; filename=\"" + HttpUtility.UrlEncode(Request.ContentEncoding.GetBytes(this.FileName)) + "\""); long size = end - begin + 1; Response.AddHeader("Content-Length", size.ToString()); // 创建一比特数组 byte[] buffer = new Byte[pack]; fileStream.Position = begin; //设置当前流位置 // 当文件大小大于0是进入循环 while (size > 0) { // 判断客户端是否仍连接在服务器 if (Response.IsClientConnected) { // 获取缓冲区中的总字节数. int length = fileStream.Read(buffer, 0, pack); // 写入数据 Response.OutputStream.Write(buffer, 0, length); // 将缓冲区的输出发送到客户端 Response.Flush(); buffer = new Byte[pack]; size = size - length; if (sleep > 0) { Thread.Sleep(sleep); } } else { //当用户断开后退出循环 size = -1; } } } }
文件的断点上传,待补充
以上是关于.net网站的文件上传读取进度条和断点下载的主要内容,如果未能解决你的问题,请参考以下文章
从进度条和alert的出现顺序来了解浏览器 UI 渲染 & JS进程