Silverlight跨浏览器支持已经有了长足的进步,而且与.NET开发语言的完美结合,这些都使得在Windows平台下开发富客户端应用Silverlight应该比Flash更有优势,当然Silverlight代替Flash应该为时尚早,而且现有的功能与Flash仍有不小差距,但是对于开发者而言早一点接触、使用的话,对于改进网站用户的体验,提高网站的交互能力和界面很有帮助。
本文就如何使用Silverlight调用Web Service进行文件上传,Silverlight用于界面显示、用户选择上传的文件、上传过程的显示(进度条)、多文件上传状态显示;web service中提供的方法将接收到的客户端发送来的文件保存到服务器的特定目录并将上传文件信息保存到XML文件。因为上传的文件一般用于向其他用户提供下载共享,所以XML文件中保存的信息是用于后续的下载信息提供源,主要包括文件名、文件大小、上传时间、下载次数、最后下载时间等。XML文件的存取采用的方法是XML序列化和反序列化。
博客地址:http://www.intersense.net/z-blog
发布软件:Live Writer + Code Formatter for Windows Live Writer
Silverlight跨浏览器支持已经有了长足的进步,而且与.NET开发语言的完美结合,这些都使得在Windows平台下开发富客户端应用Silverlight应该比Flash更有优势,当然Silverlight代替Flash应该为时尚早,而且现有的功能与Flash仍有不小差距,但是对于开发者而言早一点接触、使用的话,对于改进网站用户的体验,提高网站的交互能力和界面很有帮助。
本文就如何使用Silverlight调用Web Service进行文件上传,Silverlight用于界面显示、用户选择上传的文件、上传过程的显示(进度条)、多文件上传状态显示;web service中提供的方法将接收到的客户端发送来的文件保存到服务器的特定目录并将上传文件信息保存到XML文件。因为上传的文件一般用于向其他用户提供下载共享,所以XML文件中保存的信息是用于后续的下载信息提供源,主要包括文件名、文件大小、上传时间、下载次数、最后下载时间等。XML文件的存取采用的方法是XML序列化和反序列化。
文件下载部分的实现比较容易,后续会发布基于Silverlight的下载界面以及代码。
源代码下载:
SilverlightApplication1.Web.rar
SilverlightApplication1.rar
上传页面构成:
- DataGrid控件用于显示用户选定的待上传文件;
- 按钮“选择上传文件”点击之后打开选择文件对话框用户可以选择多个文件;
- 按钮“清除”,点击之后将DataGrid中的内容清空;
- 按钮“上传”,点击之后如果DataGrid中内容不为空,则开始逐个上传所有文件。 页面如下图所示:
上述界面对应的page.xaml如下:
Code
<UserControl
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
x:Class="SilverlightApplication1.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="600" Width="800" >
<Grid x:Name="LayoutRoot" Background="YellowGreen" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="535"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="35"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="2" Orientation="Horizontal" >
<Button Content="选择上传文件" x:Name="MyButton" Width="100" Height="20" Click="Mybutton_Click" Grid.Column="0" FontSize="12"></Button>
<Button Content="清除" x:Name="MyReset" Width="100" Height="20" Click="MyReset_Click" Grid.Column="1" FontSize="12"></Button>
<Button Content="上传" x:Name="Upload" Width="100" Height="20" Click="Upload_Click" Grid.Column="2" FontSize="12"></Button>
</StackPanel>
<StackPanel Grid.Row="1" VerticalAlignment="Center">
<ProgressBar Name="progFile" Height="20" Width="800"></ProgressBar>
</StackPanel>
<Grid Grid.Row="0">
<data:DataGrid Name="FileList" LoadingRow="DataGrid_LoadingRow">
</data:DataGrid>
</Grid>
</Grid>
</UserControl
上传界面的后台代码Page.xaml.cs:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Collections;
using System.Windows.Data;
using System.Xml;
namespace SilverlightApplication1
{
public partial class Page : UserControl
{
List<FilesClass> fl = new List<FilesClass>();
int iFileCount = 1;
public Page()
{
InitializeComponent();
}
private void Mybutton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
op.Multiselect = true;
op.ShowDialog();
if (op.Files != null)
{
foreach(FileInfo f in op.Files)
{
if ( f.Length< 1048576000)
{
FilesClass obj = new FilesClass();
obj.PropFileName = f;
obj.PropNumber = iFileCount.ToString();
fl.Add(obj);
iFileCount++;
}
else
{
MessageBox.Show("Max file size is 1 MB");
}
}
BindGrid();
}
else
{
MessageBox.Show("Select File");
}
}
private void BindGrid()
{
FileList.ItemsSource = null;
FileList.ItemsSource = fl;
FileList.SelectedIndex = -1;
FileList.Columns[0].Header = "序号";
FileList.Columns[1].Header = "文件名";
FileList.Columns[2].Header = "状态";
FileList.Columns[0].Width = new DataGridLength(80);
FileList.Columns[1].Width = new DataGridLength(600);
FileList.Columns[2].Width = new DataGridLength(100);
}
private void MyReset_Click(object sender, RoutedEventArgs e)
{
FileList.ItemsSource = null;
fl.Clear();
iFileCount = 1;
progFile.Value = 0;
}
double progVal = 0;
private void Upload_Click(object sender, RoutedEventArgs e)
{
try
{
if (fl.Count > 0)
{
progVal = (double)100 / (double)fl.Count;
for (int count = 0; count < fl.Count; count++)
{
ServiceReference1.uploadServiceSoapClient x = new SilverlightApplication1.ServiceReference1.uploadServiceSoapClient();
x.UploadFilesCompleted += new EventHandler<ServiceReference1.UploadFilesCompletedEventArgs>(UploadFileComplted);
FilesClass obj = (FilesClass) fl[count];
System.IO.FileStream str = obj.PropFileName.OpenRead();
byte[] by = new byte[str.Length];
str.Read(by, 0, by.Length);
str.Close();
x.UploadFilesAsync(obj.PropFileName.Name, by, obj.PropNumber);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void UploadFileComplted(object sender, ServiceReference1.UploadFilesCompletedEventArgs e)
{
if (e.Result != "")
{
int i = Convert.ToInt32(e.Result) - 1;
fl[i].PropStatus = "上传成功!";
BindGrid();
progFile.Value += progVal;
}
}
private void UpdateXMLFileList(int i)
{
}
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
FilesClass obj = e.Row.DataContext as FilesClass;
if (obj.PropStatus == "1")
{
e.Row.Background = new SolidColorBrush(Colors.Gray);
}
}
}
Web Service代码:
Code
还有两个用于序列化xml的辅助类:
FileDown类表示上传的文件,提供下载时需要的一些信息如文件名、文件大小、下载次数、上传时间、最后下载时间等,FileDownCollection类对应的是整个XML文件,类中包含一个ArrayList,其元素皆为FileDown类型,使用XML序列化和反序列化能够轻松地进行信息的存取。
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Serialization;
using System.Collections;
namespace SilverlightApplication1.Web
{
[Serializable]
public class FileDown
{
public FileDown(){ }
// 文件名
private string filename;
// 文件大小
private double filesize;
// 下载次数
private int downloadtimes;
// 上传时间
private DateTime timeUP;
// 最后下载时间
private DateTime timeDown;
public string FileName
{
get { return this.filename; }
set { this.filename = value; }
}
public double FileSize
{
get { return this.filesize; }
set { this.filesize = value; }
}
public int DownloadTimes
{
get { return this.downloadtimes; }
set { this.downloadtimes = value; }
}
public DateTime TimeUpload
{
get { return this.timeUP; }
set { this.timeUP = value; }
}
public DateTime TimeDownload
{
get { return this.timeDown; }
set { this.timeDown = value; }
}
}
[Serializable]
public class FileDownCollection : ICollection
{
public string CollectionName;
private ArrayList fileArray = new ArrayList();
public FileDown this[int index]
{
get { return (FileDown)fileArray[index]; }
}
public void CopyTo(Array a, int index)
{
fileArray.CopyTo(a, index);
}
public int Count
{
get { return fileArray.Count; }
}
public object SyncRoot
{
get { return this; }
}
public bool IsSynchronized
{
get { return false; }
}
public IEnumerator GetEnumerator()
{
return fileArray.GetEnumerator();
}
public void Add(FileDown f)
{
fileArray.Add(f);
}
}