当前位置:编程学习 > C#/ASP.NET >>

C#/Asp.net 结合 Delphi 实现大文件的断点续传 [Chukeh.dll]

最近手上的一个项目需要经常的应对大于 2GB 以上文件的上传及管理,目前的.net系统虽然可以上传大于 2GB 的文件,但是由于 Http 上传不是特别稳定,所以一旦中断,或者

中途无响应,那就需要从头重新传一次,这对用户确实非常不友好,所以决定在不对 .net 系统做大改动的前提下,借助 delphi 开发客户端来实现断点续传。

基本思路是,由 delphi 把要上传的文件分块,然后用 idhttp 模拟 post 请求,提交文件块,.net 以 Request.Files 方式接收数据,然后根据同时提交的 position 和 block 

参数写入临时文件,上传完毕后再重名名文件,这样客户端只要记下最后的 position 参数,就可以在任意位置开始续传文件了。

您可以到这里下载示例代码 http://www.easyfrms.com/easy/chukeh/Chukeh_1_2_0.rar
[解压后的Samples\Upload Sample目录]
http://www.easyfrms.com/easy 这里有实际的应用效果

具体代码如下:

Delphi 客户端 

定义全局变量
GLOBAL_POSITION: Int64; // 记录上传进度
GLOBAL_TASK: TUploadFile; // 上文文件线程对象

启动下载文件
GLOBAL_TASK:= TUploadFile.Create(Edit2.Text, Edit1.Text);
try
GLOBAL_TASK.Resume;
except
// 启动文件上传错误,无法启动线程
end;
暂停下载文件
if Assigned(GLOBAL_TASK) then begin
try
GLOBAL_TASK.Pause;
except
// 暂停文件上传错误,无法暂停线程
end;
取消下载文件
if Assigned(GLOBAL_TASK) then begin
try
GLOBAL_TASK.Cancel;
except
// 暂停文件上传错误,无法暂停线程
end;

TUploadFile 的源代码,请下载上面的示例代码 (抱歉,论坛不允许内容太长)

C#.Net 服务端


                try
                {
                    int _Block = Convert.ToInt32(this.Request.Params["Block"]);
                    long _Size = Convert.ToInt64(this.Request.Params["Size"]);
                    long _Position = Convert.ToInt64(this.Request.Params["Position"]);
                    string _FileName = Path.GetFileName(this.Request.Files["FileData"].FileName);
    // 这里我使用了 Chukeh.Net 这个类,这个方法的实现代码见下
                    Chukeh.Current.SavePostedFile(Context.Server.MapPath(_FileName), true, "FileData", _Size, _Position, _Block);
                    Context.Response.Write("0");
                }
                catch
                {
                    Context.Response.Write("1");
                }



        /// <summary>
        /// 保存提交的文件数据到指定位置[流方式,用于实现断点续传]
        /// </summary>
        /// <param name="FileName">string 文件保存位置</param>
        /// <param name="CreateDirectory">bool 是否创建文件夹</param>
        /// <param name="PostedFile">string 提交的文件参数名称</param>
        /// <param name="Size">long 文件尺寸</param>
        /// <param name="Position">long 进度</param>
        /// <param name="Block">int 流大小</param>
        /// <returns>Data.CResult 保存结果</returns>
        public static Data.CResult SavePostedFile(string FileName, bool CreateDirectory, string PostedFile, long Size, long Position, int Block)
        {
            if (HttpContext.Current.Request.Files[PostedFile] == null || HttpContext.Current.Request.Files[PostedFile].InputStream == null || 

HttpContext.Current.Request.Files[PostedFile].InputStream.Length <= 0)
            {
                return new Chukeh.Data.CResult(5, "提交了空数据,无法执行保存");
            }
            else
            {
                string _TempFileName = FileName + ".tmp";
                if (Position == 0)
                {
                    if (!Directory.Exists(Path.GetDirectoryName(_TempFileName)) && CreateDirectory)
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(_TempFileName));
                    }
                    if (Directory.Exists(Path.GetDirectoryName(_TempFileName)))
                    {
                        FileStream _FileStream = new FileStream(_TempFileName, FileMode.Append);
                        _FileStream.Close();
                        _FileStream.Dispose();
                    }
                    else
                    {
                        return new Chukeh.Data.CResult(4, "目标保存路径不存在或已删除");
                    }
                }
                if (Position > Size)
                {
                    IO.CFile.FileDelete(_TempFileName);
                    return new Chukeh.Data.CResult(3, "提交的数据流超出文件范围");
                }
                if (File.Exists(_TempFileName))
                {
                    byte[] _Buffer = new byte[Block];
                    FileStream _FileWriter = new FileStream(_TempFileName, FileMode.Open, FileAccess.ReadWrite);
                    if (_FileWriter.Length > Position)
                    {
                        _FileWriter.Position = Position;
                    }
                    else
                    {
                        _FileWriter.Seek(0, SeekOrigin.End);
                    }
                    HttpContext.Current.Request.Files[PostedFile].InputStream.Read(_Buffer, 0, _Buffer.Length);
                    _FileWriter.Write(_Buffer, 0, _Buffer.Length);
                    _FileWriter.Close();
                    _FileWriter.Dispose();
                    if (Position + Block >= Size)
                    {
                        File.Move(_TempFileName, FileName);
                        return new Chukeh.Data.CResult(0, "保存数据流成功,文件已保存完毕");
                    }
                    else
                    {
                        return new Chukeh.Data.CResult(1, "保存数据流成功,已写入文件 " + Base.ToSize(Position + Block));
                    }
                }
                else
                {
                    return new Chukeh.Data.CResult(2, "保存数据流失败,无法写入流至文件");
                }
            }
        } --------------------编程问答-------------------- 不知道以后会不会用到,收藏下、 --------------------编程问答-------------------- 谢谢,楼主,测试了能用
chukeh.dll 的源代码能贴出来吗 --------------------编程问答-------------------- 抱歉!不能,不过其实您也不需要啊.
下面已经贴出了你需要用到的方法的代码
补充:.NET技术 ,  ASP.NET
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,