您的位置:首页 > 其它

Silverlight中用WCF实现文件快速上传(一、基本方法)

2015-07-13 11:36 417 查看
在Silverlight中可能通过服务上传文件。通过服务上传文件可以比较方便地实现异步上传、分块上传、进度显示等等功能。因此,“Silverlight + 服务”组合可以实现比较强大类似于C/S模式中的那种上传功能。下面详细说明实现步骤。

1. 创建Silverlight应用程序。

这个是基本能力,不会的先找资料学习一下吧。

假定创建的解决方案为:UploadFiles。默认情况下存在两个项目:UploadFiles和UploadFiles.Web。

2. 添加WCF服务。

在UploadFiles.Web项目中添加WCF服务:右键→添加→新建项→选“启用 Silverlight 功能的 WCF 服务”,如果VS是英文的则为“Silverlight-enabled WCF Service”。

3. WCF服务的代码:

[c-sharp] view
plaincopy

namespace UploadFiles.Web

{

[ServiceContract(Namespace = "")]

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

public class Service1

{

[OperationContract]

public void DoWork()

{

// 在此处添加操作实现

return;

}

// 在此处添加更多操作并使用 [OperationContract] 标记它们

[OperationContract]

public void ActionUpload(string fileName, byte[] fileData, bool isAppend)

{

//文件上传所在目录

//可以按日期、文件类型或混合建立相应的文件目录,以便使用

string uploadFolder = System.Web.Hosting.HostingEnvironment.MapPath("~/upload");

//目录不存在则新建

if (!System.IO.Directory.Exists(uploadFolder))

{

System.IO.Directory.CreateDirectory(uploadFolder);

}

//文件读写模式

//如果参数为真则表示续传,以追回模式写文件

System.IO.FileMode fileMode = isAppend ? System.IO.FileMode.Append : System.IO.FileMode.Create;

//写入文件

using (System.IO.FileStream fs = new System.IO.FileStream(uploadFolder + @"/" + fileName, fileMode, System.IO.FileAccess.Write))

{

fs.Write(fileData, 0, fileData.Length);

}

}

}

}

4. Silverlight中的上传执行代码

在MainPage.xaml中添加一个执行上传的按钮,后台执行代码如下:

[c-sharp] view
plaincopy

private void Button_Click(object sender, RoutedEventArgs e)

{

//选择本地文件对话框

OpenFileDialog openFileDialog = new OpenFileDialog();

openFileDialog.Filter = "(*.*)|*.*";

//单选

openFileDialog.Multiselect = false;

if (openFileDialog.ShowDialog() == true)

{

//所选上传文件信息

FileInfo fileInfo = openFileDialog.File;

//上传文件信息

UploadFileInfo uploadFileInfo = new UploadFileInfo();

uploadFileInfo.Name = fileInfo.Name;

//文件内容

Stream stream = fileInfo.OpenRead();

uploadFileInfo.Size = (int)(stream.Length / 1024);

uploadFileInfo.Data = new List<byte[]>();

//读取指定大小的文件流内容到uploadFile.Data以便上传

int len;

long rest;

while (stream.Position > -1 && stream.Position < stream.Length)

{

rest = stream.Length - stream.Position;

//len = (rest >= 16384) ? 16384 : (int)rest; //WCF默认配置参数最大只允许16KB

len = (rest >= 2097152) ? 2097152 : (int)rest; //2MB

byte[] fileData = new byte[len];

stream.Read(fileData, 0, len);

uploadFileInfo.Data.Add(fileData);

}

stream.Close();

localService.Service1Client wcfService = new TestUploadFile_WCF.localService.Service1Client();

wcfService.ActionUploadCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(wcfService_ActionUploadCompleted);

wcfService.ActionUploadAsync(uploadFileInfo.Name, uploadFileInfo.Data[0], false, uploadFileInfo);

}

}

void wcfService_ActionUploadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)

{

if (e.Error == null)

{

UploadFileInfo uploadFileInfo = e.UserState as UploadFileInfo;

uploadFileInfo.Status += uploadFileInfo.Data[0].Length / 1024;

uploadFileInfo.Data.RemoveAt(0);

if (uploadFileInfo.Data.Count == 0)

{

btnUploadFile.Content = "Uploaded";

MessageBox.Show("文件上传成功。");

}

else

{

(sender as localService.Service1Client).ActionUploadAsync(uploadFileInfo.Name, uploadFileInfo.Data[0], true, uploadFileInfo);

btnUploadFile.Content = uploadFileInfo.Status.ToString() + "/" + uploadFileInfo.Size.ToString() + "KB Uploaded.";

}

}

}

辅助类:

[c-sharp] view
plaincopy

public class UploadFileInfo

{

//文件名

public string Name { get; set; }

//文件大小

public int Size { get; set; }

//上传状态

public int Status { get; set; }

//文件流

public List<byte[]> Data { get; set; }

}

5. 上传数据尺寸配置

默认情况下,WCF只允许最大16KB的数据块上传。按此尺寸,实测上传速度很慢。如果要修改尺寸,则要修改Web.config文件。

注意:是修改UploadFiles.Web中的Web.config,而不是UploadFiles中的ServiceReferences.ClientConfig。最开始我曾以为是修改后者,结果被困了好久,汗颜!

网上有好多文章讲修改参数的,但无一指明是修改.Web项目中的Web.config,让我困惑了好久,最后在一个英文网页中找到的答案……。

修改后的内容如下:

[c-sharp]
view plaincopy

<system.serviceModel>

<behaviors>

<serviceBehaviors>

<behavior name="UploadFiles.Web.Service1Behavior">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="false"/>

</behavior>

</serviceBehaviors>

</behaviors>

<bindings>

<customBinding>

<binding name="customBinding0">

<binaryMessageEncoding>

<readerQuotas maxArrayLength="2097152"/><!--2MB-->

</binaryMessageEncoding>

<httpTransport maxReceivedMessageSize="2147483647"/>

</binding>

</customBinding>

</bindings>

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

<services>

<service behaviorConfiguration="UploadFiles.Web.Service1Behavior" name="UploadFiles.Web.Service1">

<endpoint address="" binding="customBinding" bindingConfiguration="customBinding0" contract="UploadFiles.Web.Service1"/>

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

</service>

</services>

</system.serviceModel>

修改的结果是允许最大2MB的数据块上传。Sunpire网友(参见参考文献2)提到的要增加24KB冗余的问题,我在实测中没有遇到。即:Sunpire网友的文章中提到<customBinding>要设置2MB+24KB,才能上传2MB数据的情况我没有遇到。我实际设置2MB就能上传2MB数据。当然,我没有象Sunpire网友那样去做那么多测试,只做了1MB和2MB的测试。

6. 总结

按照上述方法,可以实现各种文件快速上传。小文件上传几乎是瞬间的事,大文件也很快。

缺点:上传时会一次性的把整个文件读入内存。进一步的解决方案是边读边上传。

参考文献:

[1]agile 的《Silverlight 3 中使用WCF上传文件 (简单进度条展示)》:/content/1759877.html

[2]Sunpire 的《Silverlight+WCF文件上传,含分段大小调节(WCF 16KB配置)、压缩Buffer调节、速度指示、批量等》:http://www.soaspx.com/dotnet/silverlight/silverlight_20100321_3357.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: