Silverlight文件上传下载实现方法(下载保存)
search了非常多的文章,总算勉强实现了。有许多不完善的地方。
在HCLoad.Web项目下新建目录Pics复制一张图片到根目录下。
图片名:Bubble.jpg右击->属性->生成操作:Resource
UC_UpDown.xaml
<UserControlx:Class="HCLoad.UC_UpDown" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="500"Height="500"> <StackPanelBackground="White"Height="450"> <ButtonContent="down"Click="Button_Click"></Button> <HyperlinkButtonContent="下载保存"NavigateUri="http://localhost:4528/download.ashx?fileName=aa.txt"TargetName="_self"x:Name="lBtnDown"/> <TextBlockx:Name="tbMsgString"Text="下载进度"TextAlignment="Center"Foreground="Green"></TextBlock> <Buttonx:Name="btnDownload"Content="DownLoadPictures"Width="150"Height="35"Margin="15"Click="btnDownload_Click"/> <BorderBackground="Wheat"BorderThickness="5"Width="400"Height="280"> <Imagex:Name="imgDownLoad"Width="400"Height="300"Margin="15"Stretch="Fill"/> </Border> <Buttonx:Name="btnUpLoad"Content="UpLoadPictures"Width="150"Height="35"Margin="15"Click="btnUpLoad_Click"/> </StackPanel> </UserControl>
UC_UpDown.xaml.cs
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Net;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Documents;
usingSystem.Windows.Input;
usingSystem.Windows.Media;
usingSystem.Windows.Media.Animation;
usingSystem.Windows.Shapes;
usingSystem.Windows.Media.Imaging;//因为要使用BitmapImage
usingSystem.IO;//因为要使用Stream
namespaceHCLoad
{
publicpartialclassUC_UpDown:UserControl
{
//1、WebClient对象一次只能启动一个请求。如果在一个请求完成(包括出错和取消)前,即IsBusy为true时,进行第二个请求,则第二个请求将会抛出NotSupportedException类型的异常
//2、如果WebClient对象的BaseAddress属性不为空,则BaseAddress与URI(相对地址)组合在一起构成绝对URI
//3、WebClient类的AllowReadStreamBuffering属性:是否对从Internet资源接收的数据做缓冲处理。默认值为true,将数据缓存在客户端内存中,以便随时被应用程序读取
//获取选定图片信息
System.IO.FileInfofileinfo;
publicUC_UpDown()
{
InitializeComponent();
}
#region下载图片
privatevoidbtnDownload_Click(objectsender,RoutedEventArgse)
{
//向指定的Url发送下载流数据请求
StringimgUrl="http://localhost:4528/Bubble.jpg";
Uriendpoint=newUri(imgUrl);
WebClientclient=newWebClient();
client.OpenReadCompleted+=newOpenReadCompletedEventHandler(OnOpenReadCompleted);
client.DownloadProgressChanged+=newDownloadProgressChangedEventHandler(clientDownloadStream_DownloadProgressChanged);
client.OpenReadAsync(endpoint);
}
voidOnOpenReadCompleted(objectsender,OpenReadCompletedEventArgse)
{
//OpenReadCompletedEventArgs.Error-该异步操作期间是否发生了错误
//OpenReadCompletedEventArgs.Cancelled-该异步操作是否已被取消
//OpenReadCompletedEventArgs.Result-下载后的Stream类型的数据
//OpenReadCompletedEventArgs.UserState-用户标识
if(e.Error!=null)
{
MessageBox.Show(e.Error.ToString());
return;
}
if(e.Cancelled!=true)
{
//获取下载的流数据(在此处是图片数据)并显示在图片控件中
//Streamstream=e.Result;
//BitmapImagebitmap=newBitmapImage();
//bitmap.SetSource(stream);
//imgDownLoad.Source=bitmap;
StreamclientStream=e.UserStateasStream;
StreamserverStream=(Stream)e.Result;
byte[]buffer=newbyte[serverStream.Length];
serverStream.Read(buffer,0,buffer.Length);
clientStream.Write(buffer,0,buffer.Length);
clientStream.Close();
serverStream.Close();
}
}
voidclientDownloadStream_DownloadProgressChanged(objectsender,DownloadProgressChangedEventArgse)
{
//DownloadProgressChangedEventArgs.ProgressPercentage-下载完成的百分比
//DownloadProgressChangedEventArgs.BytesReceived-当前收到的字节数
//DownloadProgressChangedEventArgs.TotalBytesToReceive-总共需要下载的字节数
//DownloadProgressChangedEventArgs.UserState-用户标识
this.tbMsgString.Text=string.Format("完成百分比:{0}当前收到的字节数:{1}资料大小:{2}",
e.ProgressPercentage.ToString()+"%",
e.BytesReceived.ToString(),
e.TotalBytesToReceive.ToString());
}
#endregion
#region上传图片
privatevoidbtnUpLoad_Click(objectsender,RoutedEventArgse)
{
/**/
/*
*OpenWriteCompleted-在打开用于上传的流完成时(包括取消操作及有错误发生时)所触发的事件
*WriteStreamClosed-在写入数据流的异步操作完成时(包括取消操作及有错误发生时)所触发的事件
*UploadProgressChanged-上传数据过程中所触发的事件。如果调用OpenWriteAsync()则不会触发此事件
*Headers-与请求相关的的标头的key/value对**
*OpenWriteAsync(Uriaddress,stringmethod,ObjectuserToken)-打开流以使用指定的方法向指定的URI写入数据
*Uriaddress-接收上传数据的URI
*stringmethod-所使用的HTTP方法(POST或GET)
*ObjectuserToken-需要上传的数据流
*/
OpenFileDialogopenFileDialog=newOpenFileDialog()
{//弹出打开文件对话框要求用户自己选择在本地端打开的图片文件
Filter="JpegFiles(*.jpg)|*.jpg|AllFiles(*.*)|*.*",
Multiselect=false//不允许多选
};
if(openFileDialog.ShowDialog()==true)//.DialogResult.OK)
{
//fileinfo=openFileDialog.Files;//取得所选择的文件,其中Name为文件名字段,作为绑定字段显示在前端
fileinfo=openFileDialog.File;
if(fileinfo!=null)
{
WebClientwebclient=newWebClient();
stringuploadFileName=fileinfo.Name.ToString();//获取所选文件的名字
#region把图片上传到服务器上
UriupTargetUri=newUri(String.Format("http://localhost:4528/WebClientUpLoadStreamHandler.ashx?fileName={0}",uploadFileName),UriKind.Absolute);//指定上传地址
webclient.OpenWriteCompleted+=newOpenWriteCompletedEventHandler(webclient_OpenWriteCompleted);
webclient.Headers["Content-Type"]="multipart/form-data";
webclient.OpenWriteAsync(upTargetUri,"POST",fileinfo.OpenRead());
webclient.WriteStreamClosed+=newWriteStreamClosedEventHandler(webclient_WriteStreamClosed);
#endregion
}
else
{
MessageBox.Show("请选取想要上载的图片!!!");
}
}
}
voidwebclient_OpenWriteCompleted(objectsender,OpenWriteCompletedEventArgse)
{
//将图片数据流发送到服务器上
//e.UserState-需要上传的流(客户端流)
StreamclientStream=e.UserStateasStream;
//e.Result-目标地址的流(服务端流)
StreamserverStream=e.Result;
byte[]buffer=newbyte[4096];
intreadcount=0;
//clientStream.Read-将需要上传的流读取到指定的字节数组中
while((readcount=clientStream.Read(buffer,0,buffer.Length))>0)
{
//serverStream.Write-将指定的字节数组写入到目标地址的流
serverStream.Write(buffer,0,readcount);
}
serverStream.Close();
clientStream.Close();
}
voidwebclient_WriteStreamClosed(objectsender,WriteStreamClosedEventArgse)
{
//判断写入是否有异常
if(e.Error!=null)
{
System.Windows.Browser.HtmlPage.Window.Alert(e.Error.Message.ToString());
}
else
{
System.Windows.Browser.HtmlPage.Window.Alert("图片上传成功!!!");
}
}
#endregion
privatevoidButton_Click(objectsender,RoutedEventArgse)
{
//这种方法搞不定,好像提示跨域操作。
//提示:错误:UnhandledErrorinSilverlightApplication跨线程访问无效。
//UriupTargetUri=newUri(String.Format("http://localhost:4528/download.ashx?filename={0}","123.jpg"),UriKind.Absolute);//指定上传地址
//WebRequestrequest=WebRequest.Create(upTargetUri);
//request.Method="GET";
//request.ContentType="application/octet-stream";
//request.BeginGetResponse(newAsyncCallback(RequestReady),request);
//通过调用js代码下载,比较简单。
System.Windows.Browser.HtmlPage.Window.Eval("window.location.href='http://localhost:4528/download.ashx?filename=123.jpg';");
}
voidRequestReady(IAsyncResultasyncResult)
{
MessageBox.Show("RequestComplete");
}
}
}
在HCLoad.Web项目下新建WebClientUpLoadStreamHandler.ashx
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.IO;//因为要用到Stream
namespaceHCLoad.Web
{
publicclassWebClientUpLoadStreamHandler:IHttpHandler
{
publicvoidProcessRequest(HttpContextcontext)
{
//获取上传的数据流
stringfileNameStr=context.Request.QueryString["fileName"];
Streamsr=context.Request.InputStream;
try
{
stringfilename="";
filename=fileNameStr;
byte[]buffer=newbyte[4096];
intbytesRead=0;
//将当前数据流写入服务器端文件夹ClientBin下
stringtargetPath=context.Server.MapPath("Pics/"+filename+".jpg");
using(FileStreamfs=File.Create(targetPath,4096))
{
while((bytesRead=sr.Read(buffer,0,buffer.Length))>0)
{
//向文件中写信息
fs.Write(buffer,0,bytesRead);
}
}
context.Response.ContentType="text/plain";
context.Response.Write("上传成功");
}
catch(Exceptione)
{
context.Response.ContentType="text/plain";
context.Response.Write("上传失败,错误信息:"+e.Message);
}
finally
{sr.Dispose();}
}
publicboolIsReusable
{
get
{
returnfalse;
}
}
}
}
新建download.ashx
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Services;
usingSystem.Net;
namespaceHCLoad.Web
{
///<summary>
///$codebehindclassname$的摘要说明
///</summary>
publicclassdownload:IHttpHandler
{
privatelongChunkSize=102400;//100K每次读取文件,只读取100K,这样可以缓解服务器的压力
publicvoidProcessRequest(HttpContextcontext)
{
//stringfileName="123.jpg";//客户端保存的文件名
StringfileName=context.Request.QueryString["filename"];
stringfilePath=context.Server.MapPath("Bubble.jpg");
System.IO.FileInfofileInfo=newSystem.IO.FileInfo(filePath);
if(fileInfo.Exists==true)
{
byte[]buffer=newbyte[ChunkSize];
context.Response.Clear();
System.IO.FileStreamiStream=System.IO.File.OpenRead(filePath);
longdataLengthToRead=iStream.Length;//获得下载文件的总大小
context.Response.ContentType="application/octet-stream";
//通知浏览器下载文件而不是打开
context.Response.AddHeader("Content-Disposition","attachment;filename="+HttpUtility.UrlEncode(fileName,System.Text.Encoding.UTF8));
while(dataLengthToRead>0&&context.Response.IsClientConnected)
{
intlengthRead=iStream.Read(buffer,0,Convert.ToInt32(ChunkSize));//读取的大小
context.Response.OutputStream.Write(buffer,0,lengthRead);
context.Response.Flush();
dataLengthToRead=dataLengthToRead-lengthRead;
}
context.Response.Close();
context.Response.End();
}
//context.Response.ContentType="text/plain";
//context.Response.Write("HelloWorld");
}
publicboolIsReusable
{
get
{
returnfalse;
}
}
}
}
参考:
http://www.cnblogs.com/wsdj-ittech/archive/2009/08/26/1554056.html
http://www.cnblogs.com/wsdj-ittech/archive/2009/08/25/1553534.html
http://www.cnblogs.com/wmt1708/archive/2009/03/07/1405009.html
http://topic.csdn.net/u/20090918/10/5e41ab52-f514-46b5-ae6a-d69ddb197213.html
http://www.cnblogs.com/wsdj-ittech/archive/2009/08/25/1553534.html
http://www.cnblogs.com/gwazy/archive/2009/04/02/1427781.html
http://www.cnblogs.com/ewyb/archive/2009/12/10/1621020.html
http://blog.csdn.net/emily1900/archive/2010/06/08/5655726.aspx