Silverlight 实现文件下载
文件下载通常采用附件的方式在http响应头里面设置Content-disposition值为"attachment;filename=" + filepath,以及为Content-Length设置下载文件总长度(单位字节)来实现。
本文是采用Silverlight实现文件下载,服务端用asp.net一般处理程序(.ashx)处理。
以下是项目结构图:
MainPage类源码如下:
View Code
1 namespace SilverlightDownAndUploadFile 2 { 3 public delegate void SaveFileHandler(int bytesRead, byte[] buffer); 4 public delegate void UploadFileHandler(int bytesRead); 5 public partial class MainPage : UserControl 6 { 7 private SaveFileDialog sfd; 8 private OpenFileDialog ofd; 9 Stream stream = null; 10 BinaryWriter bw = null; 11 private long fileLen = 0; 12 private long readFileLen = 0;//已下载长度 13 private AutoResetEvent autoEvent = new AutoResetEvent(false); 14 15 public MainPage() 16 { 17 InitializeComponent(); 18 } 19 20 #region 下载 21 private void ShowDownResult(bool isSuccess) 22 { 23 this.Dispatcher.BeginInvoke( 24 () => 25 { 26 if (isSuccess) 27 MessageBox.Show("下载完毕."); 28 else 29 MessageBox.Show("下载出错!"); 30 }); 31 } 32 33 private void UpdateDownProgress(int bytesRead) 34 { 35 readFileLen += bytesRead; 36 37 double rate = Convert.ToDouble(readFileLen) / Convert.ToDouble(fileLen); 38 double percent = Math.Round(rate, 2) * 100; 39 downProgress.Visibility = Visibility.Visible; 40 downProgress.pgBar.Value = percent; 41 downProgress.txtProgress.Text = percent + "%"; 42 43 } 44 45 private void FlushToFile(int bytesRead, byte[] buffer) 46 { 47 try 48 { 49 if (null == stream) 50 { 51 stream = sfd.OpenFile(); 52 bw = new BinaryWriter(stream); 53 } 54 55 bw.Write(buffer, 0, bytesRead); 56 bw.Flush(); 57 UpdateDownProgress(bytesRead); 58 autoEvent.Set(); 59 } 60 catch (Exception ex) 61 { } 62 } 63 64 private void RequestAndDownFile() 65 { 66 try 67 { 68 HttpWebRequest request = CreateWebRequest("http://localhost:13953/Download.ashx", "GET"); 69 HttpWebRequest webRequest = request; 70 webRequest.BeginGetResponse( 71 (asyncResult) => 72 { 73 if (webRequest.HaveResponse) 74 { 75 try 76 { 77 WebResponse response = webRequest.EndGetResponse(asyncResult);//易发生异常 78 fileLen = Convert.ToInt64(response.Headers["Content-Length"]);//文件长度 79 80 Stream responseStream = response.GetResponseStream(); 81 int maxBufLength = 20 * 1024;//20K 82 byte[] buffer = new byte[maxBufLength]; 83 int bytesRead = responseStream.Read(buffer, 0, maxBufLength); 84 while (bytesRead != 0) 85 { 86 Dispatcher.BeginInvoke(new SaveFileHandler(FlushToFile), bytesRead, buffer); 87 autoEvent.WaitOne(); 88 buffer = new byte[maxBufLength]; 89 bytesRead = responseStream.Read(buffer, 0, maxBufLength); 90 } 91 92 ShowDownResult(true); 93 } 94 catch (Exception ex) 95 { 96 ShowDownResult(false); 97 } 98 finally 99 { 100 this.Dispatcher.BeginInvoke( 101 () => 102 { 103 if (null != bw) 104 bw.Close(); 105 if (null != stream) 106 stream.Close(); 107 }); 108 } 109 } 110 }, null); 111 112 } 113 catch (Exception ex) 114 { 115 ShowDownResult(false); 116 } 117 } 118 119 private void btnDownload_Click(object sender, RoutedEventArgs e) 120 { 121 fileLen = 0; 122 readFileLen = 0; 123 sfd = new SaveFileDialog(); 124 sfd.Filter = "(*.rar)|*.rar"; 125 126 if (sfd.ShowDialog() == true) 127 { 128 RequestAndDownFile(); 129 } 130 } 131 132 private static HttpWebRequest CreateWebRequest(string requestUriString, string httpMethod) 133 { 134 try 135 { 136 string ticks = Guid.NewGuid().ToString(); 137 requestUriString = requestUriString + "/" + ticks; 138 HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(requestUriString)); 139 request.Method = httpMethod; 140 141 return request; 142 } 143 catch (Exception ex) 144 { 145 return null; 146 } 147 } 148 #endregion 149 150 /// <summary> 151 /// 获了实际接读取到的字节数组 152 /// </summary> 153 /// <param name="buffer"></param> 154 /// <param name="bytesRead"></param> 155 /// <returns></returns> 156 private byte[] GetNewBuffer(byte[] buffer, int bytesRead) 157 { 158 byte[] newBuffer = new byte[bytesRead]; 159 for (int i = 0; i < bytesRead; i++) 160 { 161 newBuffer[i] = buffer[i]; 162 } 163 return newBuffer; 164 } 165 }
Download.ashx源码如下:
View Code
1 namespace SilverlightDownAndUploadFile.Web 2 { 3 /// <summary> 4 /// Download 的摘要说明 5 /// </summary> 6 public class Download : IHttpHandler 7 { 8 9 public void ProcessRequest(HttpContext context) 10 { 11 try 12 { 13 //context.Response.ContentType = "text/plain"; 14 //context.Response.Write("Hello World"); 15 //要下载文件路径 16 string path = "d:/test.rar"; //context.Server.MapPath("~/Files/lan.txt"); 17 context.Response.ContentType = Utils.GetContentType(path);//设置ContentType 18 context.Response.AppendHeader("Content-disposition", "attachment;filename=" + path); 19 context.Response.BufferOutput = false; 20 context.Response.Buffer = false; 21 using (FileStream fs = File.OpenRead(path)) 22 { 23 BinaryReader br = new BinaryReader(fs); 24 long fileLen = br.BaseStream.Length; 25 context.Response.AppendHeader("Content-Length", fileLen.ToString()); 26 27 int bytesRead = 0;//读取到的字节数 28 int maxBufLength = 20 * 1024;//20K 29 byte[] buffer = new byte[maxBufLength]; 30 bytesRead = br.Read(buffer, 0, maxBufLength); 31 while (bytesRead != 0) 32 { 33 byte[] newBuffer = GetNewBuffer(buffer, bytesRead); 34 context.Response.BinaryWrite(newBuffer); 35 context.Response.Flush(); 36 buffer = new byte[maxBufLength]; 37 bytesRead = br.Read(buffer, 0, maxBufLength); 38 } 39 context.Response.Flush(); 40 context.Response.End(); 41 } 42 } 43 catch (Exception ex) 44 { 45 46 } 47 } 48 49 /// <summary> 50 /// 获了实际接读取到的字节数组 51 /// </summary> 52 /// <param name="buffer"></param> 53 /// <param name="bytesRead"></param> 54 /// <returns></returns> 55 private byte[] GetNewBuffer(byte[] buffer, int bytesRead) 56 { 57 byte[] newBuffer = new byte[bytesRead]; 58 for (int i = 0; i < bytesRead; i++) 59 { 60 newBuffer[i] = buffer[i]; 61 } 62 return newBuffer; 63 } 64 65 public bool IsReusable 66 { 67 get 68 { 69 return false; 70 } 71 } 72 } 73 }
完整项目源码可从http://download.csdn.net/detail/lianchangshuai/4998494下载。