Silverlight实现上传及下载(一)-WCF 上传下载实现
用到的知识简介
Silverlight调用WCF简介
请参考
Silverlight调用WebClient简介
Siverlight中很多时候我们需要上传下载功能,WebClient提供了两种工作方式来实现上传下载功能。(可参考http://www.xiaoniusoft.com/Libary/Details/2872.aspx上的资料)
A、以字符串形式下载和上传数据
使用WebClient可以以字符串形式下载数据,当请求一个指定地址的字符串时,调用DownloadStringAsync方法,操作完成后将触发 DownloadStringCompleted事件,在该事件处理方法中能够接收到一个类型为 DownloadStringCompletedEventArgs的参数,它的Result属性的类型为String,我们可以通过该属性来获得最终的字符串结果,它可以是一段普通的文本或一段XML文本等。
B、 以流形式下载和上传数据
使用WebClient同样可以以流形式下载数据,当请求下载的资源是一个流时,可调用OpenReadAsync方法,此操作完成后将触发 OpenReadCompleted事件,在该事件处理方法中能够接收到一个类型为OpenReadCompletedEventArgs的参数,它的 Result属性类型为Stream,使用此属性能够获取到最终的流结果。
WebClient的主要函数如下:
•OpenReadAsync 打开流向指定资源的可读流。
•OpenWriteAsync 打开一个流以将数据写入指定的资源。这些方法不会阻止调用线程。
•DownloadStringAsync 以字符串形式下载位于指定 Uri 的资源。
•UploadStringAsync 将指定的字符串上载到指定的资源。这些方法不会阻止调用线程。
WebClient的主要事件如下:
•OpenReadCompleted 在异步资源读取操作完成时发生。
•OpenWriteCompleted 在打开流以将数据写入资源的异步操作完成时发生。
•DownloadStringCompleted 在异步资源下载操作完成时发生。
•DownloadProgressChanged 在异步下载操作成功传输部分或全部数据后发生。
•UploadStringCompleted 在异步字符串上载操作完成时发生。
•UploadProgressChanged 在异步上载操作成功转换部分或全部数据后发生。
Silverlight调用WebService简介
在Silverlight中较为简单的一种上传文件的方式,就是将客户端的文件序列化为Byte[]字符组,然后服务端使用WebService连接客户端的数据并还原为文件。
当然我问在使用WebService完成上传下载功能的时候,还得使用一个“一般处理程序”来辅助完成此项任务。
WCF方式思路及功能实现
难点解析
一.上传文件时的端口不一致问题
一般有两种方法来操作端口。
一种是通过右键Silverlight Web服务端选择“属性”子菜单,在Web选项卡中将“使用Visual Studio开发服务器”的“特定端口”勾选,并填入固定的端口号;
另一种是在Uri中通过代码动态获得当前的web请求的端口号;
这里推荐使用第二种方法。例如:HtmlPage.Document.DocumentUri.Port ,其中通过System.Windows.Browser命名空间下的HtmlPage类来动态捕获端口,当然也可以通过给方法中的DocumentUri的其他属性值来获得服务端主机的IP地址等其他信息。
二.上传文件存放路径问题
Silverlight客户端不支持对服务端路径的直接操作。故而一般通过某种数据服务间接操作。其实现方式是通过Uri地址中加入数据服务名的方法将该操作请求转到服务端中建立的服务处理类中来进行。如WCF服务中可通过Client.Endpoint.Address=new EndpointAddress("http://localhost:" +HtmlPage.Document.DocumentUri.Port +"/SilverlightUploader.Web/FileService.svc")来将客户端操作引入服务端进行。
上传功能实现
实现思路:将本地打开的文件流读入字节数组中,并将该字节数组传递到服务端,在服务端将字节数组还原为文件并保存。
使用OpenFileDialog获得上传文件流,并写入字节数组传递到服务端。
private void cmdUpload_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openDialog = new OpenFileDialog();
if (openDialog.ShowDialog() == true)
{
Try
{
using (Stream stream = openDialog.File.OpenRead())
{
// 限制上传文件大小
if (stream.Length > 5000000)
{
MessageBox.Show("文件不得大于5M “);
}
else
{
byte[] data = new byte[stream.Length];
stream.Read(data, 0, (int)stream.Length);//将当前流读入字节数组中
client.UploadFileAsync(openDialog.File.Name, data);//将文件名和字节数组传递到服务端
}
}
}
catch
{
MessageBox.Show(“上传文件失败”);
}
}
}
// 服务端还原文件并保存
// 在服务端建立的WCF服务中加入契约函数如下:
/// <summary>
/// 还原文件并保存
/// </summary>
/// <param name="fileName">上传文件名</param>
/// <param name="data">上传文件字节数组</param>
[OperationContract]
public void UploadFile(string fileName, byte[] data)
{
//服务端建立一个名为Files的文件夹,filePath即为该目录映射的物理路径
filePath = HttpContext.Current.Server.MapPath("Files");
string file = Path.Combine(filePath, Path.GetFileName(fileName));
using (FileStream fs = new FileStream(file, FileMode.Create))
{
fs.Write(data, 0, (int)data.Length); //还原文件
}
}
//下载功能实现
//服务端将存在的文件转化为字节数组回传到客户端
/// <summary>
/// 将指定文件转化为字节数组传回客户端
/// </summary>
/// <param name="fileName">指定文件名</param>
/// <returns>文件字节数组</returns>
[OperationContract]
public byte[] DownloadFile(string fileName)
{
//路径的定义同上
string file = Path.Combine(filePath, Path.GetFileName(fileName));
using (FileStream fs = new FileStream(file, FileMode.Open))
{
byte[] data = new byte[fs.Length];
fs.Read(data, 0, (int)fs.Length);
return data;
}
}
//客户端还原文件并保存
//在单击事件中通过SaveFileDialog来还原文件
private void cmdDownload_Click(object sender, RoutedEventArgs e)
{
if (lstFiles.SelectedIndex != -1)
{
SaveFileDialog saveDialog = new SaveFileDialog();
if (saveDialog.ShowDialog() == true)
{
client.DownloadFileAsync(“这里传入下载文件名”,saveDialog);
//注意:此处传入了一个服务端为定义的一个参数,目的是为了标识异步操作完成时接受文件的SaveFileDialog,但WCF服务中的函 数定义为public byte[] DownloadFile(string fileName)无需加入第二个参数的定义。
}
}
}
private void client_DownloadFileCompleted(object sender, DownloadFileCompletedEventArgs e)
{
if (e.Error == null)
{
SaveFileDialog saveDialog = (SaveFileDialog)e.UserState;//获得标识的SaveFileDialog
using (Stream stream = saveDialog.OpenFile())
{
stream.Write(e.Result, 0, e.Result.Length);
}
}
else
{
MessageBox.Show(“下载失败”);
}
}