一般来说,文件上传总是需要的,可以通过ashx及其wcf或其它方式实现,这里主要是wcf实现方式,并附之简单的进度显示。。。
1. silverlight 项目一般有silverlight和silverlight.web(asp.net)两个基本项目,在这里我们需要在silverlight.web(asp.net)项目中添加一个Silverlight enabled wcf service文件,其功能主要是实现文件上传。
WCF文件所在项目:
WCF文件类型:
相应代码如下:
Code
namespace BlackCore.Web
{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
}
// Add more operations here and mark them with [OperationContract]
[OperationContract]
public void ActionUpload(string fileName, byte[] fileContext, 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 = System.IO.FileMode.Create;
//如果参数为真则表示续传,以追回模式写文件
if (isAppend)
{
fileMode = System.IO.FileMode.Append;
}
//写入文件
using (System.IO.FileStream fs = new System.IO.FileStream(uploadFolder + @"\" + fileName, fileMode, System.IO.FileAccess.Write))
{
fs.Write(fileContext, 0, fileContext.Length);
}
return;
}
}
}
namespace BlackCore.Web
{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
}
// Add more operations here and mark them with [OperationContract]
[OperationContract]
public void ActionUpload(string fileName, byte[] fileContext, 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 = System.IO.FileMode.Create;
//如果参数为真则表示续传,以追回模式写文件
if (isAppend)
{
fileMode = System.IO.FileMode.Append;
}
//写入文件
using (System.IO.FileStream fs = new System.IO.FileStream(uploadFolder + @"\" + fileName, fileMode, System.IO.FileAccess.Write))
{
fs.Write(fileContext, 0, fileContext.Length);
}
return;
}
}
}
2. 在Silverlight中添加服务引用就OK,然后在相应的界面实现即可,简单实现如下:
在MainPage.xaml加入了如下一个Button
<Button Grid.Row="1" Grid.Column="3" x:Name="btnWCFUpload" Content="WCFUpload" Height="20" Width="80" />
在MainPage.xaml.cs中加入如下
Code
public MainPage()
{
this.btnWCFUpload.Click += new RoutedEventHandler(btnWCFUpload_Click);
}
/// <summary>
/// WCF 文件上传
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void btnWCFUpload_Click(object sender, RoutedEventArgs e)
{
//选择本地文件对话框
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "(*.*)|*.*";
//单选
openFileDialog.Multiselect = false;
if (openFileDialog.ShowDialog() == true)
{
//所选上传文件信息
FileInfo fileInfo = openFileDialog.File;
//上传文件信息
UploadFileInfo uploadFile = new UploadFileInfo();
uploadFile.Name = fileInfo.Name;
//文件内容
Stream stream = fileInfo.OpenRead();
uploadFile.Size = stream.Length / 1024.00;
uploadFile.Context = new List<byte[]>();
//读取指定大小的文件流内容到uploadFile.Context以便上传
int b;
while (stream.Position > -1 && stream.Position < stream.Length)
{
if (stream.Length - stream.Position >= 3000)
{
b = 3000;
}
else
{
b = (int)(stream.Length - stream.Position);
}
byte[] filebyte = new byte[b];
stream.Read(filebyte, 0, b);
uploadFile.Context.Add(filebyte);
}
stream.Close();
UploadService.Service1Client wcfService = new BlackCore.UploadService.Service1Client();
wcfService.ActionUploadCompleted +=new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(wcfService_ActionUploadCompleted);
wcfService.ActionUploadAsync(uploadFile.Name, uploadFile.Context[0], false, uploadFile);
}
}
void wcfService_ActionUploadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
UploadFileInfo uploadFile = e.UserState as UploadFileInfo;
uploadFile.CompletedStatus += uploadFile.Context[0].Length / 1024.00;
uploadFile.Context.RemoveAt(0);
if (uploadFile.Context.Count == 0)
{
btnWCFUpload.Content = "WCFUpload";
MessageBox.Show("文件上传成功!");
}
else
{
(sender as UploadService.Service1Client).ActionUploadAsync(uploadFile.Name, uploadFile.Context[0], true, uploadFile);
btnWCFUpload.Content = uploadFile.CompletedStatus.ToString() + "/" + uploadFile.Size.ToString() + "KByte";
}
}
}
/// <summary>
/// 当前上传文件信息
/// </summary>
public class UploadFileInfo
{
/// <summary>
/// 文件名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public double Size { get; set; }
/// <summary>
/// 上传完成状态
/// </summary>
public double CompletedStatus { get; set; }
/// <summary>
/// 文件流
/// </summary>
public List<byte[]> Context { get; set; }
}
public MainPage()
{
this.btnWCFUpload.Click += new RoutedEventHandler(btnWCFUpload_Click);
}
/// <summary>
/// WCF 文件上传
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void btnWCFUpload_Click(object sender, RoutedEventArgs e)
{
//选择本地文件对话框
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "(*.*)|*.*";
//单选
openFileDialog.Multiselect = false;
if (openFileDialog.ShowDialog() == true)
{
//所选上传文件信息
FileInfo fileInfo = openFileDialog.File;
//上传文件信息
UploadFileInfo uploadFile = new UploadFileInfo();
uploadFile.Name = fileInfo.Name;
//文件内容
Stream stream = fileInfo.OpenRead();
uploadFile.Size = stream.Length / 1024.00;
uploadFile.Context = new List<byte[]>();
//读取指定大小的文件流内容到uploadFile.Context以便上传
int b;
while (stream.Position > -1 && stream.Position < stream.Length)
{
if (stream.Length - stream.Position >= 3000)
{
b = 3000;
}
else
{
b = (int)(stream.Length - stream.Position);
}
byte[] filebyte = new byte[b];
stream.Read(filebyte, 0, b);
uploadFile.Context.Add(filebyte);
}
stream.Close();
UploadService.Service1Client wcfService = new BlackCore.UploadService.Service1Client();
wcfService.ActionUploadCompleted +=new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(wcfService_ActionUploadCompleted);
wcfService.ActionUploadAsync(uploadFile.Name, uploadFile.Context[0], false, uploadFile);
}
}
void wcfService_ActionUploadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
UploadFileInfo uploadFile = e.UserState as UploadFileInfo;
uploadFile.CompletedStatus += uploadFile.Context[0].Length / 1024.00;
uploadFile.Context.RemoveAt(0);
if (uploadFile.Context.Count == 0)
{
btnWCFUpload.Content = "WCFUpload";
MessageBox.Show("文件上传成功!");
}
else
{
(sender as UploadService.Service1Client).ActionUploadAsync(uploadFile.Name, uploadFile.Context[0], true, uploadFile);
btnWCFUpload.Content = uploadFile.CompletedStatus.ToString() + "/" + uploadFile.Size.ToString() + "KByte";
}
}
}
/// <summary>
/// 当前上传文件信息
/// </summary>
public class UploadFileInfo
{
/// <summary>
/// 文件名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public double Size { get; set; }
/// <summary>
/// 上传完成状态
/// </summary>
public double CompletedStatus { get; set; }
/// <summary>
/// 文件流
/// </summary>
public List<byte[]> Context { get; set; }
}
3. 效果如下
当然,如果用wcf实现方式,可能会给发布带来一定麻烦。。。
因为在ClientBin中的BlackCore.xap(这里我的项目的压缩包)中的ServiceReferences.ClientConfig中有生成的配置信息,如果要部署是需要更改的
Servicereferences.ClientConfig文件配置信息如下:
Code
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_Service1">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:16827/UPloadWCFService.svc"
binding="customBinding" bindingConfiguration="CustomBinding_Service1"
contract="UploadService.Service1" name="CustomBinding_Service1" />
</client>
</system.serviceModel>
</configuration>
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_Service1">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:16827/UPloadWCFService.svc"
binding="customBinding" bindingConfiguration="CustomBinding_Service1"
contract="UploadService.Service1" name="CustomBinding_Service1" />
</client>
</system.serviceModel>
</configuration>
所以,使用WCF还应该想个办法解决发布部署问题,也就算WCF文件上传是成功的。
此问题本人暂时没有解决,如遇能人,恳请赐教,谢谢!