码迷,mamicode.com
首页 > Windows程序 > 详细

c# 文件的断点续传

时间:2017-11-06 19:06:27      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:drop   mode   image   format   emd   pen   obj   客户端   split   

一、开篇描述

本篇博客所描述的断点续传功能是基于c#语言,服务器端采用.net mvc框架,客户端采用winform框架。

本篇博客实现断点续传功能的基本思路:1)服务器端是把接收到的文件流,追加到已有的文件;2)客户端是把文件流截段上传;

其实,任何一种计算机语言基于这个思路,都可以实现断点续传的功能。

二、服务器端

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            //string ip = Request.UserHostAddress;
            //string port = Request.ServerVariables["REMOTE_PORT"].ToString();
            return View();
        }

        /// <summary>
        /// 获取续传点。
        /// </summary>
        /// <param name="md5Name"></param>
        /// <returns></returns>
        public string GetFileResumePoint(string md5Name)
        {
            var saveFilePath = Server.MapPath("~/Images/") + md5Name;
            if (System.IO.File.Exists(saveFilePath))
            {
                var fs = System.IO.File.OpenWrite(saveFilePath);
                var fsLength = fs.Length.ToString();
                fs.Close();
                return fsLength;
            }
            return "0";
        }

        /// <summary>
        /// 文件续传。
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public HttpResponseMessage FileResume()
        {
            var fileStream = Request.InputStream;
            var md5Name = Request.QueryString["md5Name"];
            SaveAs(Server.MapPath("~/Images/") + md5Name, fileStream);
            return new HttpResponseMessage(HttpStatusCode.OK);
        }

        /// <summary>
        /// 给已有文件追加文件流。
        /// </summary>
        /// <param name="saveFilePath"></param>
        /// <param name="stream"></param>
        private void SaveAs(string saveFilePath, System.IO.Stream stream)
        {
            //接收到的字节信息。
            long startPosition = 0;
            long endPosition = 0;
            var contentRange = Request.Headers["Content-Range"];//contentRange样例:bytes 10000-20000/59999
            if (!string.IsNullOrEmpty(contentRange))
            {
                contentRange = contentRange.Replace("bytes", "").Trim();
                contentRange = contentRange.Substring(0, contentRange.IndexOf("/"));
                string[] ranges = contentRange.Split(‘-‘);
                startPosition = long.Parse(ranges[0]);
                endPosition = long.Parse(ranges[1]);
            }
            //默认写针位置。
            System.IO.FileStream fs;
            long writeStartPosition = 0;
            if (System.IO.File.Exists(saveFilePath))
            {
                fs = System.IO.File.OpenWrite(saveFilePath);
                writeStartPosition = fs.Length;
            }
            else
            {
                fs = new System.IO.FileStream(saveFilePath, System.IO.FileMode.Create);
            }
            //调整写针位置。
            if (writeStartPosition > endPosition)
            {
                fs.Close();
                return;
            }
            else if (writeStartPosition < startPosition)
            {
                fs.Close();
                return;
            }
            else if (writeStartPosition > startPosition && writeStartPosition < endPosition)
            {
                writeStartPosition = startPosition;
            }
            fs.Seek(writeStartPosition, System.IO.SeekOrigin.Current);
            //向文件追加文件流。
            byte[] nbytes = new byte[512];
            int nReadSize = 0;
            nReadSize = stream.Read(nbytes, 0, 512);
            while (nReadSize > 0)
            {
                fs.Write(nbytes, 0, nReadSize);
                nReadSize = stream.Read(nbytes, 0, 512);
            }
            fs.Close();
        }

    }
}

  

三、客户端

1 界面如下:

技术分享

2 代码如下:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// 定义委托。
        /// </summary>
        /// <param name="text"></param>
        delegate void ChangeText(string text);

        /// <summary>
        /// 暂停标记。
        /// </summary>
        int flag = 0;

        /// <summary>
        /// 上传的文件路径。
        /// </summary>
        string filePath;

        /// <summary>
        /// 上传的文件md5值。
        /// </summary>
        string md5Str;

        /// <summary>
        /// 上传的文件续传点。
        /// </summary>
        long startPoint;

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 委托方法。
        /// </summary>
        /// <param name="text"></param>
        public void ChangeLabelText(string text)
        {
            this.label1.Text = text;
        }

        /// <summary>
        /// 得到文件的MD5值。
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public string GetFileMd5(string filePath)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            Byte[] hashBytes = md5.ComputeHash(fs);
            fs.Close();
            return BitConverter.ToString(hashBytes).Replace("-", "");
        }

        /// <summary>
        /// 得到文件的续传点。
        /// </summary>
        /// <param name="md5Str"></param>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public long GetFileResumePoint(string md5Str, string fileExtension)
        {
            System.Net.WebClient webClient = new System.Net.WebClient();
            string urlStr = "http://file.taiji.com/Home/GetFileResumePoint?md5Name=" + md5Str + fileExtension;
            byte[] infoBytes = webClient.DownloadData(urlStr);
            string result = System.Text.Encoding.UTF8.GetString(infoBytes);
            if (string.IsNullOrEmpty(result))
            {
                return 0;
            }
            return Convert.ToInt64(result);
        }

        public void ResumeFileThread()
        {
            MessageBox.Show(ResumeFile("http://file.taiji.com/Home/FileResume", filePath, startPoint, 1024 * 128, md5Str));
        }

        public string ResumeFile(string hostUrl, string filePath, long startPoint, int byteCount, string md5Str)
        {
            string result = "上传成功!";
            byte[] data;
            System.Net.WebClient webClient = new System.Net.WebClient();
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            long fileLength = fs.Length;
            BinaryReader bReader = new BinaryReader(fs);
            try
            {
                #region 续传处理
                if (startPoint == fileLength)
                {
                    result = "文件秒传!";
                }
                if (startPoint >= 1 && startPoint <= fileLength - 1)
                {
                    fs.Seek(startPoint, SeekOrigin.Current);
                }
                #endregion
                #region 分割文件上传
                for (; startPoint <= fileLength - 1; startPoint = startPoint + byteCount)
                {
                    int step = 0;
                    if (startPoint + byteCount > fileLength)
                    {
                        data = new byte[Convert.ToInt32(fileLength - startPoint)];
                        bReader.Read(data, 0, Convert.ToInt32(fileLength - startPoint));
                        step = Convert.ToInt32(fileLength - startPoint);
                    }
                    else
                    {
                        data = new byte[byteCount];
                        bReader.Read(data, 0, byteCount);
                        step = byteCount;
                    }

                    webClient.Headers.Remove(HttpRequestHeader.ContentRange);
                    webClient.Headers.Add(HttpRequestHeader.ContentRange, "bytes " + startPoint + "-" + (startPoint + step) + "/" + fs.Length);
                    webClient.UploadData(hostUrl + "?md5Name=" + md5Str + Path.GetExtension(filePath), "POST", data);
                    this.BeginInvoke(new ChangeText(ChangeLabelText), (startPoint + step) + "/" + fileLength);
                pause:
                    if (flag == 1)
                    {
                        Thread.Sleep(1000);
                        goto pause;
                    }
                }
                #endregion
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            bReader.Close();
            fs.Close();
            return result;
        }

        /// <summary>
        /// 上传按钮点击事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                filePath = openFileDialog.FileName;
                md5Str = GetFileMd5(filePath);
                startPoint = GetFileResumePoint(md5Str, Path.GetExtension(filePath));
                ThreadStart ts = new ThreadStart(ResumeFileThread);
                Thread t = new Thread(ts);
                t.Start();
            }
        }

        /// <summary>
        /// 暂停按钮点击事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            flag = 1;
        }

        /// <summary>
        /// 继续按钮点击事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            flag = 0;
        }

        /// <summary>
        /// 允许拖拽。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            this.AllowDrop = true;
        }

        /// <summary>
        /// 拖拽上传。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
                MessageBox.Show("准备上传" + files.Length + "个文件!");
                foreach (string file in files)
                {
                    MessageBox.Show("开始上传文件:" + file);
                    filePath = file;
                    md5Str = GetFileMd5(filePath);
                    startPoint = GetFileResumePoint(md5Str, Path.GetExtension(filePath));
                    ThreadStart ts = new ThreadStart(ResumeFileThread);
                    Thread t = new Thread(ts);
                    t.Start();
                }
            }
        }

    }
}

  

c# 文件的断点续传

标签:drop   mode   image   format   emd   pen   obj   客户端   split   

原文地址:http://www.cnblogs.com/by-lhc/p/7794350.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!