.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;
            }
        }
    }
}

文件的断点上传,待补充

时间: 2024-12-20 05:20:46

.net网站的文件上传读取进度条和断点下载的相关文章

atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7

1. 实现原理 1 2. 大的文件上传原理::使用applet 1 3. 新的bp 2 1. 性能提升---分割小文件上传,避免一次使用内存使用过大的 2 2. Uuid还是原来文件名称:: 2 3. 监听器频繁地被调用 2 4. 结合wz easyui 2 4. 选型 2 5. Uploadify::yash js+flash 3 6. commons-fileupload:: 3 7. COS这个工具O'Reilly公司 3 8. 大的文件上传组件总结 3 5. 林吧实现ui Ajax+jq

atitit. 文件上传带进度条 atiUP 设计 java c# php

atitit. 文件上传带进度条 atiUP 设计 java c# php 1. 设计要求 1 2. 原理and 架构 1 3. ui 2 4. spring mvc 2 5. springMVC.xml 3 6. struts extand url 3 7. behide code 3 8. 简化设计 3 1. 设计要求 带进度条 完成提示动画效果.. 2. 原理and 架构 如果需要显示进度条,实时显示文件上传进度 需要使用Ajaxj技术..up到个在的iframe黑头.. 工作原理 其实际

简单实现一个文件上传的进度条

新手初学web 文件上传做完了 进度做了 没有进度条只有文字 不太好看  需要做个进度条  没有美工 网上很多的 进度条 需要图片 还有各种框架 看着好麻烦 只好自己弄一个 还挺简单的 没想象的那么复杂  分享一下 jsp页面 <tr> <td width="100">图片</td> <td> <div style="width: 450px;"> <div class="file-box&

Struts2文件上传带进度条,虽然不是很完美

好久没有写东西,最近在做个项目,要用到文件h 传的,以前虽然也做上传,但是总觉得不好用 ,现在和队友合作做了一个带进度条的上传,觉得还行~~和大家分享一下. 首先说一下大概是这样实现的,在我们平时的上传表单里面,除了文件上传之外,也许还有其他的信息需要填写的,这样问题就来了:点击上传按钮之后,这个表单都封装并提交上去了,在上传完成后整个页面就跳转了.而且也不利于我们验证用户输入.很多人这样做的,把这2个操作分开,当然这样也行... 我们这样做:一个普通页面(可以用于填写所有信息的),一个文件上传

.Net neatupload上传控件实现文件上传的进度条

1. 引入bin文件 (可以到neatupload官网下载,也可以到教育厅申报系统中找) 2. 将控件加入到工具栏,在工具栏中点鼠标右键,如图: 3. 加入neatuplaod这个文件夹(可以到neatupload官网下载,也可以到教育厅申报系统中找) 4. Webconfig的配置(3个地方) <configSections>配置节下配置: <!--配置NeatUpload sectionGroup配置节--> <sectionGroup name="system

html5拖拽事件 xhr2 实现文件上传 含进度条

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <meta charset="utf-8"> <meta name="viewport&

BootStrap Progressbar 实现大文件上传的进度条

1.首先实现大文件上传,如果是几兆或者几十兆的文件就用基本的上传方式就可以了,但是如果是大文件上传的话最好是用分片上传的方式.我这里主要是使用在客户端进行分片读取到服务器段,然后保存,到了服务器段读取完了之后将分片数据进行组合. 2.前端代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UploadTest2.aspx.cs" Inherits="Htm

jquery 实现拖动文件上传加进度条

通过对文件的拖动实现文件的上传,主要用到的是HTML5的ondrop事件,上传内容通道FormData传输: //进度条 <div class="parent-dlg" > <div class="progress-label">0%</div> <div class="son"></div> </div> //要拖动到的地方 <div class="main

php实现大文件上传带进度条

1.使用PHP的创始人 Rasmus Lerdorf 写的APC扩展模块来实现(http://pecl.php.net/package/apc) APC实现方法: 安装APC,参照官方文档安装,可以使用PECL模块安装方法快速简捷,这里不说明 配置php.ini,设置参数 apc.rfc1867=1 ,使APC支持上传进度条功能,在APC源码说明文档里面有说明 代码范例: 大文件(50G)上传的实现细节: 服务端接收文件数据的处理逻辑代码: 2.使用PECL扩展模块uploadprogress实