之前討論過了 Silverlight通過 WCF實現上傳的方法,現在看看另一種Silverlight實現上傳的方法 :WebClient類實現上傳,同時WEBCLIENT的 OPENWRITE也是官方提供的通常的上傳方式,因爲他完全就是HTTP實現上傳的原本模式,及建立HTTP連接,打開一個可寫入流,然後將文件流寫入到HTTP寫入流中實現,而WCF是通過傳遞字節數組參數的方法,兩則之間看似差不多,實際上工作原理很不同。
webclient類中有幾個方法,其中大部分都是請求獲取相應流,只有openwrite方法是寫入流。所以我們使用該方法實現上傳。
工作方式:
Silverlight打開文件,獲取文件流,webclient 調用openwrite方法,請求服務器,打開一個可以寫入流 InputStream
當該可寫入流可用的時候,相應openwrite異步方法的一個回調事件,在該事件中將文件流寫入到HTTP的可寫入流。服務器端接收到輸入流後寫入到文件流保存。
服務器端:(我擦用ASHX作爲服務器端接收頁,因爲我們不需要返回什麼信息,只接受請求,所以沒用ASPX頁,不過要使用ASPX也可以)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;
namespace WebApp4SL
{
/// <summary>
/// $codebehindclassname$ 的摘要說明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebClientUpload : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
Stream s = context.Request.InputStream;
FileStream fs = new FileStream(context.Server.MapPath("UploadFile") + "/" + "asdf.jpg",FileMode.Create);
byte[] bytes = new byte[s.Length];
s.Read(bytes,0,bytes.Length);
fs.Write(bytes,0,bytes.Length);
fs.Flush();
fs.Close();
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
客戶端處理代碼:
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;
namespace SilverlightTest
{
public partial class WebClientUpLoad : UserControl
{
public WebClientUpLoad()
{
InitializeComponent();
}
private void openfile_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
if (op.ShowDialog() == true)
{
FileStream fs = op.File.OpenRead();
WebClient wc = new WebClient();
wc.OpenWriteCompleted += new OpenWriteCompletedEventHandler(wc_OpenWriteCompleted);
wc.OpenWriteAsync(new Uri("WebClientUpload.ashx",UriKind.Relative),"POST",fs);
}
}
void wc_OpenWriteCompleted(object sender, OpenWriteCompletedEventArgs e)
{
try
{
Stream fs = (Stream)e.UserState;
Stream inputstream = e.Result;
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
inputstream.Write(bytes, 0, bytes.Length);
inputstream.Close();
fs.Close();
}
catch
{
info.Text = e.Error.InnerException.Message;
}
}
}
}
界面:(實在獻醜,界面基本上就個按鈕會用到,因爲只是爲了說明WEBCLIENT的上傳,所以沒做什麼界面上的開發)
<UserControl x:Class="SilverlightTest.WebClientUpLoad"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Button Height="24" Margin="0,8,8,0" VerticalAlignment="Top" Content="瀏覽" Width="69" HorizontalAlignment="Right" x:Name="openfile" Click="openfile_Click" />
<TextBlock Height="24" Margin="8,8,81,0" VerticalAlignment="Top" Text="請選擇文件" TextWrapping="Wrap" x:Name="filepath"/>
<TextBlock Margin="8,51,8,0" Text="" TextWrapping="Wrap" VerticalAlignment="Top" Height="96" x:Name="info"/>
</Grid>
</UserControl>
WEBCLIENT 的OPENWRITE還有個UploadProgressChanged事件,該事件指定好對應的處理函數後還可以用來獲取上傳進度,所以用webclient來實現上傳還是非常方便的,與WCF比較起來,WCF可以自由的設置參數,但是WCF的字節數組參數長度是有限制的雖然可以在WEBCONFIG裏進行設置,但是WCF實現上傳不是官方提供的解決方案;Webclient 的Openwrite方法是官方提供的文件上傳解決方案,工作原理繼承傳統的HTTP文件上傳,同時由於發起讀取文件寫入流都是在客戶端異步進行,所以,及時要實現分塊也非常容易(webclient的其他大部分方法不允許在之前的請求沒完成前進行第2次請求,但是openwrite的文檔中沒用說明限制,我自己也沒實驗過,51過後再研究),但是webclient請求服務器傳遞參數上不夠靈活,部署方面也沒有WCF那麼鬆散,所以WCF上傳和webclient上傳都是可行的,但是具體項目具體分析,採取最好的最適當的方式實現。