【www.bbyears.com--Silverlight】
文件下载通常采用附件的方式在http响应头里面设置Content-disposition值为"attachment;filename=" + filepath,以及为Content-Length设置下载文件总长度(单位字节)来实现。
本文是采用Silverlight实现文件下载,服务端用asp.net一般处理程序(.ashx)处理。
以下是项目结构图:
MainPage类源码如下:
代码如下View Code
namespace SilverlightDownAndUploadFile
{
public delegate void SaveFileHandler(int bytesRead, byte[] buffer);
public delegate void UploadFileHandler(int bytesRead);
public partial class MainPage : UserControl
{
private SaveFileDialog sfd;
private OpenFileDialog ofd;
Stream stream = null;
BinaryWriter bw = null;
private long fileLen = 0;
private long readFileLen = 0;//已下载长度
private AutoResetEvent autoEvent = new AutoResetEvent(false);
public MainPage()
{
InitializeComponent();
}
#region 下载
private void ShowDownResult(bool isSuccess)
{
this.Dispatcher.BeginInvoke(
() =>
{
if (isSuccess)
MessageBox.Show("下载完毕.");
else
MessageBox.Show("下载出错!");
});
}
private void UpdateDownProgress(int bytesRead)
{
readFileLen += bytesRead;
double rate = Convert.ToDouble(readFileLen) / Convert.ToDouble(fileLen);
double percent = Math.Round(rate, 2) * 100;
downProgress.Visibility = Visibility.Visible;
downProgress.pgBar.Value = percent;
downProgress.txtProgress.Text = percent + "%";
}
private void FlushToFile(int bytesRead, byte[] buffer)
{
try
{
if (null == stream)
{
stream = sfd.OpenFile();
bw = new BinaryWriter(stream);
}
bw.Write(buffer, 0, bytesRead);
bw.Flush();
UpdateDownProgress(bytesRead);
autoEvent.Set();
}
catch (Exception ex)
{ }
}
private void RequestAndDownFile()
{
try
{
HttpWebRequest request = CreateWebRequest("http://localhost:13953/Download.ashx", "GET");
HttpWebRequest webRequest = request;
webRequest.BeginGetResponse(
(asyncResult) =>
{
if (webRequest.HaveResponse)
{
try
{
WebResponse response = webRequest.EndGetResponse(asyncResult);//易发生异常
fileLen = Convert.ToInt64(response.Headers["Content-Length"]);//文件长度
Stream responseStream = response.GetResponseStream();
int maxBufLength = 20 * 1024;//20K
byte[] buffer = new byte[maxBufLength];
int bytesRead = responseStream.Read(buffer, 0, maxBufLength);
while (bytesRead != 0)
{
Dispatcher.BeginInvoke(new SaveFileHandler(FlushToFile), bytesRead, buffer);
autoEvent.WaitOne();
buffer = new byte[maxBufLength];
bytesRead = responseStream.Read(buffer, 0, maxBufLength);
}
ShowDownResult(true);
}
catch (Exception ex)
{
ShowDownResult(false);
}
finally
{
this.Dispatcher.BeginInvoke(
() =>
{
if (null != bw)
bw.Close();
if (null != stream)
stream.Close();
});
}
}
}, null);
}
catch (Exception ex)
{
ShowDownResult(false);
}
}
private void btnDownload_Click(object sender, RoutedEventArgs e)
{
fileLen = 0;
readFileLen = 0;
sfd = new SaveFileDialog();
sfd.Filter = "(*.rar)|*.rar";
if (sfd.ShowDialog() == true)
{
RequestAndDownFile();
}
}
private static HttpWebRequest CreateWebRequest(string requestUriString, string httpMethod)
{
try
{
string ticks = Guid.NewGuid().ToString();
requestUriString = requestUriString + "/" + ticks;
HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(requestUriString));
request.Method = httpMethod;
return request;
}
catch (Exception ex)
{
return null;
}
}
#endregion
///
/// 获了实际接读取到的字节数组
///
///
///
///
private byte[] GetNewBuffer(byte[] buffer, int bytesRead)
{
byte[] newBuffer = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
{
newBuffer[i] = buffer[i];
}
return newBuffer;
}
}
Download.ashx源码如下:
代码如下View Code
namespace SilverlightDownAndUploadFile.Web
{
///
/// Download 的摘要说明
///
public class Download : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
try
{
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");
//要下载文件路径
string path = "d:/test.rar"; //context.Server.MapPath("~/Files/lan.txt");
context.Response.ContentType = Utils.GetContentType(path);//设置ContentType
context.Response.AppendHeader("Content-disposition", "attachment;filename=" + path);
context.Response.BufferOutput = false;
context.Response.Buffer = false;
using (FileStream fs = File.OpenRead(path))
{
BinaryReader br = new BinaryReader(fs);
long fileLen = br.BaseStream.Length;
context.Response.AppendHeader("Content-Length", fileLen.ToString());
int bytesRead = 0;//读取到的字节数
int maxBufLength = 20 * 1024;//20K
byte[] buffer = new byte[maxBufLength];
bytesRead = br.Read(buffer, 0, maxBufLength);
while (bytesRead != 0)
{
byte[] newBuffer = GetNewBuffer(buffer, bytesRead);
context.Response.BinaryWrite(newBuffer);
context.Response.Flush();
buffer = new byte[maxBufLength];
bytesRead = br.Read(buffer, 0, maxBufLength);
}
context.Response.Flush();
context.Response.End();
}
}
catch (Exception ex)
{
}
}
///
/// 获了实际接读取到的字节数组
///
///
///
///
private byte[] GetNewBuffer(byte[] buffer, int bytesRead)
{
byte[] newBuffer = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
{
newBuffer[i] = buffer[i];
}
return newBuffer;
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
文件上传
通过web进行文件上传,一般要使用form表单,在silverlight里面没有内置form表单功能,参考牛人文章,实现Silverlight文件上传。只要Web.config文件中httpRuntime节点的maxRequestLength属性足够大,上传就不受限制。
项目结构图:
MainPage类源码:
View Code
namespace SilverlightDownAndUploadFile
{
public partial class MainPage : UserControl
{
private OpenFileDialog ofd;
private AutoResetEvent autoEvent = new AutoResetEvent(false);
public MainPage()
{
InitializeComponent();
}
private static HttpWebRequest CreateWebRequest(string requestUriString, string httpMethod)
{
try
{
string ticks = Guid.NewGuid().ToString();
requestUriString = requestUriString + "/" + ticks;
HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(requestUriString));
request.Method = httpMethod;
return request;
}
catch (Exception ex)
{
return null;
}
}
#region 上传
private void ReadFileToRequestStream(BinaryReader fileStream, HttpWebRequest request)
{
try
{
request.BeginGetRequestStream((requestAsyncResult) =>
{
Stream requestStream = null;
try
{
requestStream = request.EndGetRequestStream(requestAsyncResult);
if (null != requestStream)
{
SilverlightMultipartFormData form = new SilverlightMultipartFormData();
//form.AddFormField("devilField", "中国人");
int maxBufferLen = 25 * 1024;
byte[] buffer = new byte[maxBufferLen];
int bytesRead = fileStream.Read(buffer, 0, maxBufferLen);
int i = 0;
while (bytesRead != 0)
{
i++;
byte[] newBuffer = GetNewBuffer(buffer, bytesRead);
form.AddStreamFile("package" + i, "package" + i, newBuffer);
buffer = new byte[maxBufferLen];
bytesRead = fileStream.Read(buffer, 0, maxBufferLen);
}
form.PrepareFormData();//结束
fileStream.Close();
request.ContentType = "multipart/form-data; boundary=" + form.Boundary;
foreach (byte byt in form.GetFormData())
{
requestStream.WriteByte(byt);
}
requestStream.Close();
autoEvent.Set();//开始上传
}
}
catch (Exception ex)
{ }
finally
{
if (null != requestStream)
requestStream.Close();
if (null != fileStream)
fileStream.Close();
}
}, null);
}
catch (Exception ex)
{
}
}
private void RequestAndUploadFile(BinaryReader br)
{
try
{
if (null == br) return;
HttpWebRequest request = CreateWebRequest("http://localhost:13953/Upload.ashx", "POST");
ReadFileToRequestStream(br, request);
autoEvent.WaitOne();//等待流写入完毕
//上传
request.BeginGetResponse(
(asyncResult) =>
{
if (request.HaveResponse)
{
try
{
WebResponse response = request.EndGetResponse(asyncResult);
Stream responseStream = response.GetResponseStream();
int bufferLen = 1024;
byte[] buffer = new byte[bufferLen];
int bytesRead = responseStream.Read(buffer, 0, bufferLen);
responseStream.Close();
string responseText = System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead);
ShowUploadResult(true);
}
catch (Exception ex)
{
ShowUploadResult(false);
}
}
}, null);
}
catch (Exception ex)
{
ShowUploadResult(false);
}
}
private void btnUpload_Click(object sender, RoutedEventArgs e)
{
ofd = new OpenFileDialog();
ofd.Filter = "(*.rar)|*.rar";
ofd.Multiselect = false;
if (ofd.ShowDialog() == true)
{
uploadProgress.Visibility = Visibility.Visible;
BinaryReader br = new BinaryReader(ofd.File.OpenRead());
RequestAndUploadFile(br);
}
}
private void ShowUploadResult(bool isSucess)
{
this.Dispatcher.BeginInvoke(
() =>
{
uploadProgress.Visibility = Visibility.Collapsed;
if (isSucess)
MessageBox.Show("上传成功");
else
MessageBox.Show("上传失败.");
});
}
#endregion
///
/// 获了实际接读取到的字节数组
///
///
///
///
private byte[] GetNewBuffer(byte[] buffer, int bytesRead)
{
byte[] newBuffer = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
{
newBuffer[i] = buffer[i];
}
return newBuffer;
}
}
}
Upload.ashx文件源码:
代码如下View Code
namespace SilverlightDownAndUploadFile.Web
{
///
/// Upload 的摘要说明
///
public class Upload : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");
Stream stream = null;
try
{
string path = context.Server.MapPath("~/Files/upload.rar");
int i = 0;
while (true)
{
i++;
string packageName = "package" + i;
HttpPostedFile uploadFile = context.Request.Files[packageName];
if (null != uploadFile)
{
stream = context.Request.Files[packageName].InputStream;
FileStream fs = null;
if (i == 1 && File.Exists(path))
{
fs = new FileStream(path, FileMode.Create, FileAccess.Write);
}
else
{
fs = new FileStream(path, FileMode.Append, FileAccess.Write);
}
using (BinaryWriter bw = new BinaryWriter(fs))
{
int maxBufferLen = 20 * 1024;//20K
byte[] buffer = new byte[maxBufferLen];
int bytesRead = stream.Read(buffer, 0, maxBufferLen);
while (bytesRead != 0)
{
byte[] newBuff = GetNewBuffer(buffer, bytesRead);
bw.Write(newBuff, 0, newBuff.Length);
buffer = new byte[maxBufferLen];
bytesRead = stream.Read(buffer, 0, maxBufferLen);
}
//返回本次上传字节数
context.Response.Write(stream.Length);
context.Response.Flush();
}
stream.Close();
fs.Close();
}
else
{
if (i != 1)
break;
else
i = 0;
}
}
context.Response.Write("Upload Success!");
context.Response.Flush();
context.Response.End();
}
catch (Exception ex)
{
}
finally
{
if (null != stream)
stream.Close();
}
}
///
/// 获取实际读取到的字节数组
///