Webclient 文件異步下載以及上傳,進度顯示

客戶端文件下載
public class DownloadTools
    {
        /// <summary>
        /// 下載實體
        /// </summary>
        private WebClient client;

        /// <summary>
        /// 文件存儲路徑
        /// </summary>
        private string tempFilePath;

        /// <summary>
        /// 下載文件的臨時文件名
        /// </summary>
        private string tempFileName;

        /// <summary>
        /// 下載進度條
        /// </summary>
        private ProgressBar pbDownload;

        /// <summary>
        /// 下載百分比
        /// </summary>
        private Label lbDownload;

        /// <summary>
        /// 構造函數
        /// </summary>
        public DownloadTools(ProgressBar pbDownload,Label lbDownload)
        {
            this.pbDownload = pbDownload;
            this.lbDownload = lbDownload;

            client = new WebClient();
            client.DownloadFileCompleted += Client_DownloadFileCompleted;
            client.DownloadProgressChanged += Client_DownloadProgressChanged;
        }

        /// <summary>
        /// 異步下載
        /// </summary>
        /// <param name="serverPath">服務地址</param>
        /// <param name="webHeaderCollection">請求頭部信息</param>
        public void DownloadFileAsync(string serverPath)
        {
            FolderBrowserDialog folder = new FolderBrowserDialog();
            folder.Description = "選擇文件存放目錄";
            if (folder.ShowDialog() == DialogResult.OK)
            {
                tempFilePath = folder.SelectedPath;

                if (!Directory.Exists(tempFilePath))
                {
                    MessageBox.Show(tempFilePath + " 文件路徑或部分路徑不存在");
                    return;
                }

                Uri serverUri = new Uri(serverPath);

                tempFileName = Guid.NewGuid().ToString() + ".temp";

                //下載路徑必須包含路徑和文件名
                string filePath = Path.Combine(tempFilePath, tempFileName);

                //client.Headers = webHeaderCollection;
                client.DownloadFileAsync(serverUri, filePath);
            }
        }

        /// <summary>
        /// 文件下載進度顯示
        /// </summary>
        private void Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            var responseHeaders = client.ResponseHeaders;

            int totalLength;
            if (responseHeaders != null)
            {
                bool isParseOk = int.TryParse(responseHeaders["ContentLength"], out totalLength);

                if (isParseOk)
                {
                    int Value = (int)e.BytesReceived;
                    pbDownload.Minimum = 0;
                    pbDownload.Maximum = totalLength;
                    pbDownload.Value = Value;
                    lbDownload.Text = totalLength == 0 ? "%" : ((int)(100.0 * Value / totalLength)).ToString() + "%";
                }
            }
        }

        /// <summary>
        /// 下載完成後,刪除臨時文件,賦予服務器上的文件名
        /// </summary>
        private void Client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            var responseHeaders = client.ResponseHeaders;

            string downloadFileName = HttpUtility.UrlDecode(responseHeaders["ContentFileName"]);

            if (responseHeaders["ContentError"] != null)
            {
                string error = HttpUtility.UrlDecode(responseHeaders["ContentError"]);
                MessageBox.Show(error);
                File.Delete(Path.Combine(tempFilePath, tempFileName));
            }
            else
            {
                if (e.Error != null)
                {
                    if (e.Error.InnerException != null)
                    {
                        MessageBox.Show(e.Error.InnerException.Message);
                    }
                    else
                    {
                        MessageBox.Show(e.Error.Message);
                    }
                }
                else
                {
                    //替換文件名字
                    string sourcePath = Path.Combine(tempFilePath, tempFileName);
                    string destPath = Path.Combine(tempFilePath, downloadFileName);
                    destPath = JudgeIsExist(destPath);
                    File.Move(sourcePath, destPath);
                    File.Delete(Path.Combine(tempFilePath, tempFileName));
                }
            }
        }

        /// <summary>
        /// 避免文件重複
        /// </summary>
        private string JudgeIsExist(string path)
        {
            if (File.Exists(path))
            {
                string extension = Path.GetExtension(path);
                string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
                path = Path.Combine(tempFilePath, fileNameWithoutExtension + "-副本" + extension);
                return JudgeIsExist(path);
            }
            else
            {
                return path;
            }
        }
    }
客戶端文件上傳
public class UploadTools
    {
        /// <summary>
        /// 下載實體
        /// </summary>
        private WebClient client;

        /// <summary>
        /// 上傳進度條
        /// </summary>
        private ProgressBar pbUpload;

        /// <summary>
        /// 上傳百分比
        /// </summary>
        private Label lbUpload;

        /// <summary>
        /// 構造函數
        /// </summary>
        public UploadTools(ProgressBar pbUpload, Label lbUpload)
        {
            this.pbUpload = pbUpload;
            this.lbUpload = lbUpload;

            client = new WebClient();
            client.UploadProgressChanged += Client_UploadProgressChanged;
            client.UploadFileCompleted += Client_UploadFileCompleted;
        }

        /// <summary>
        /// 異步上傳
        /// </summary>
        /// <param name="serverPath">服務地址</param>
        /// <param name="webHeaderCollection">請求頭</param>
        public void UploadFileAsync(string serverPath)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Multiselect = false;
            if (fileDialog.ShowDialog() == DialogResult.OK)
            {
                string filePath = fileDialog.FileName;
                if (!string.IsNullOrEmpty(filePath))
                {
                    //擴展名
                    string extension = Path.GetExtension(filePath);
                    //文件名
                    string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
                    //帶擴展名的文件名
                    string fileName = Path.GetFileName(filePath);
                    //client.Headers = webHeaderCollection;
                    client.UploadFileAsync(new Uri(serverPath), filePath);
                }
            }
        }

        /// <summary>
        /// 上傳完畢
        /// </summary>
        private void Client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
        {
            var responseHeaders = client.ResponseHeaders;
            if (responseHeaders != null && responseHeaders["ContentError"] != null)
            {
                string error = HttpUtility.UrlDecode(responseHeaders["ContentError"]);
                MessageBox.Show(error);
            }
            else
            {
                if (e.Error != null)
                {
                    if (e.Error.InnerException != null)
                    {
                        MessageBox.Show(e.Error.InnerException.Message);
                    }
                    else
                    {
                        MessageBox.Show(e.Error.Message);
                    }
                }
            }
        }

        /// <summary>
        /// 上傳進度
        /// </summary>
        private void Client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
        {
            pbUpload.Minimum = 0;
            pbUpload.Maximum = (int)e.TotalBytesToSend;
            pbUpload.Value = (int)e.BytesSent;
            lbUpload.Text = e.ProgressPercentage.ToString();
        }
    }

調用例子
/// <summary>
        /// 上傳文件
        /// </summary>
        private void BtnUpload_Click(object sender, EventArgs e)
        {
            //構造請求頭信息
            //WebHeaderCollection webHeaderCollection = new WebHeaderCollection();
            //webHeaderCollection.Add("FunctionType", "ModelFileRelated");
            //webHeaderCollection.Add("RequestType", "Upload");
            //webHeaderCollection.Add("ProjectId", "");
            //webHeaderCollection.Add("FileType", HttpUtility.UrlEncode(""));
            //webHeaderCollection.Add("FileRemarks", HttpUtility.UrlEncode(""));
            //webHeaderCollection.Add("ModelId", "");
            string allParams = "?FunctionType=Upload";
            allParams += "&";
            allParams += "&FileType=" + HttpUtility.UrlEncode("");
            allParams += "&FileRemarks=" + HttpUtility.UrlEncode("");
            allParams += "&ModelId=";

            new UploadTools(pbUpload, lbUpload).UploadFileAsync("ModelFileUploadAndDownload.ashx" + allParams);
        }

        /// <summary>
        /// 點擊文件下載
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnDownload_Click(object sender, EventArgs e)
        {
            //構造請求頭信息
            //WebHeaderCollection webHeaderCollection = new WebHeaderCollection();
            //webHeaderCollection.Add("FunctionType", "");
            //webHeaderCollection.Add("RequestType", "");
            //webHeaderCollection.Add("FileGuid", "");
            string allParams = "?FunctionType=Download";
            allParams += "&";
            new DownloadTools(pbDownload,lbDownload).DownloadFileAsync("ModelFileUploadAndDownload.ashx" + allParams);
        }

服務端IHttpHandler
public class ModelFileDownload : IHttpHandler
    {
        /// <summary>
        /// 數據庫實體
        /// </summary>
        private FileImageEntities fileInfoSqlServer = new FileImageEntities();

        /// <summary>
        /// 文件存儲目錄
        /// </summary>
        private string fileSaveDirectory = ConfigurationManager.AppSettings["modelFileSavePath"];

        public void ProcessRequest(HttpContext context)
        {
            NameValueCollection allParams = context.Request.Params;
            string functionType = allParams["FunctionType"];
            if (!string.IsNullOrEmpty(functionType))
            {
                if (functionType.Equals("Upload"))
                {
                    //如果上傳文件 
                    SaveFileFromClient(context);
                }
                else if (functionType.Equals("Download"))
                {
                    //如果下載文件
                    PrepareForResponse(context);
                }
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 響應前數據準備
        /// </summary>
        /// <param name="guid"></param>
        private void PrepareForResponse(HttpContext context)
        {
            string fileGuid = context.Request.Params["FileGuid"];
            if (!string.IsNullOrEmpty(fileGuid))
            {
                //查詢數據庫中存儲的文件路徑
                var fileInfo //文件存儲信息
                if (fileInfo != null && fileInfo.FilePath != null && fileInfo.FileName != null && fileInfo.FileExtension != null)
                {
                    ResponseFile(@fileInfo.FilePath, fileInfo.FileName + fileInfo.FileExtension);
                }
                else
                {
                    ErrorResponse("文件不存在");
                }
            }
            else
            {
                ErrorResponse("文件不存在");
            }
        }

        /// <summary>
        /// 根據文件路徑下載指定文件
        /// </summary>
        public void ResponseFile(string filepath, string filename)
        {
            Stream iStream = null;
            byte[] buffer = new Byte[1024 * 10];
            int length;
            long dataToRead;
            if (System.IO.File.Exists(filepath))
            {
                iStream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                dataToRead = iStream.Length;

                HttpContext.Current.Response.ContentType = "application/octet-stream";//直接用鏈接再網頁上下載
                HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(filename));
      //自定義字段
                HttpContext.Current.Response.AddHeader("ContentFileName", HttpUtility.UrlEncode(filename));
                HttpContext.Current.Response.AppendHeader("ContentLength", dataToRead.ToString());
                while (dataToRead > 0)
                {
                    if (HttpContext.Current.Response.IsClientConnected)
                    {
                        length = iStream.Read(buffer, 0, buffer.Length);
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
                        HttpContext.Current.Response.Flush();
                        dataToRead = dataToRead - length;
                    }
                    else
                    {
                        dataToRead = -1;
                    }
                }
                if (iStream != null) iStream.Close();
                HttpContext.Current.Response.End();
            }
            else
            {
                ErrorResponse("文件不存在");
            }
        }

        /// <summary>
        /// 保存文件到服務器
        /// </summary>
        public void SaveFileFromClient(HttpContext context)
        {
            NameValueCollection allParams = context.Request.Params;
            string projectId = allParams["ProjectId"];
            string modelId = allParams["ModelId"];
            string fileType = HttpUtility.UrlDecode(allParams["FileType"]);
            string fileRemarks = allParams["FileRemarks"] == null ? null : HttpUtility.UrlDecode(allParams["FileRemarks"]);
            string dateTime = DateTime.Now.ToString("yy-MM-dd");

            HttpFileCollection files = context.Request.Files;
            if (files != null && files.Count > 0)
            {

                #region 文件存儲路徑
                string fileNameWithExtension = files[0].FileName;
                string fileNameWithOutExtension = Path.GetFileNameWithoutExtension(fileNameWithExtension);
                string extension = Path.GetExtension(fileNameWithExtension);

                string newFileSaveAbsolutePath = fileSaveDirectory + @"\" + dateTime;

                if (!Directory.Exists(newFileSaveAbsolutePath))
                {
                    Directory.CreateDirectory(newFileSaveAbsolutePath);
                }

                //判斷文件路徑是否已存在
                string fileGuid = JudgeIsExist(newFileSaveAbsolutePath, extension);

                string fileSaveAbsolutePath = Path.Combine(newFileSaveAbsolutePath, fileGuid + extension);
                #endregion

                files[0].SaveAs(fileSaveAbsolutePath);//存儲文件
            }
        }

        /// <summary>
        /// 錯誤返回 ContentError
        /// </summary>
        private static void ErrorResponse(string error)
        {
            HttpContext.Current.Response.AddHeader("ContentError", HttpUtility.UrlEncode(error));
            HttpContext.Current.Response.End();
        }

        /// <summary>
        /// 判斷文件存儲路徑是否已存在
        /// </summary>
        /// <returns>fileGuid</returns>
        private string JudgeIsExist(string newFileSaveAbsolutePath,string extension)
        {
            string fileGuid = Guid.NewGuid().ToString();
            string fileSaveAbsolutePath = Path.Combine(newFileSaveAbsolutePath, fileGuid + extension);
            if (!System.IO.File.Exists(fileSaveAbsolutePath))
            {
                return fileGuid;
            }
            else
            {
                return JudgeIsExist(newFileSaveAbsolutePath, extension);
            }
        }
    }





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章