Webclient 檔案非同步下載以及上傳,進度顯示
阿新 • • 發佈:2018-12-27
客戶端檔案下載
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);
}
}
}