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(“下載失敗”);
}
}