通過Web Services上傳和下載文件

隨着Internet技術的發展和跨平臺需求的日益增加,Web Services的應用越來越廣,我們不但需要通過Web Services傳遞字符串信息,而且需要傳遞二進制文件信息。下面,我們就分別介紹如何通過Web Services從服務器下載文件到客戶端和從客戶端通過Web Services上載文件到服務器。

一:通過Web Services顯示和下載文件

我們這裏建立的Web Services的名稱爲GetBinaryFile,提供兩個公共方法:分別是GetImage()和GetImageType(),前者返回二進制文件字節數組,後者返回文件類型,其中,GetImage()方法有一個參數,用來在客戶端選擇要顯示或下載的文件名字。這裏我們所顯示和下載的文件可以不在虛擬目錄下,採用這個方法的好處是:可以根據權限對文件進行顯示和下載控制,從下面的方法我們可以看出,實際的文件位置並沒有在虛擬目錄下,因此可以更好地對文件進行權限控制,這在對安全性有比較高的情況下特別有用。這個功能在以前的ASP程序中可以用Stream對象實現。爲了方便讀者進行測試,這裏列出了全部的源代碼,並在源代碼裏進行介紹和註釋。

首先,建立GetBinaryFile.asmx文件:

我們可以在VS.NET裏新建一個C#的aspxWebCS工程,然後“添加新項”,選擇“Web服務”,並設定文件名爲:GetBinaryFile.asmx,在“查看代碼”中輸入以下代碼,即:GetBinaryFile.asmx.cs:

using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.UI; using System.Web.Services; using System.IO; namespace xml.sz.luohuedu.net.aspxWebCS { /// <summary> /// GetBinaryFile 的摘要說明。 /// Web Services名稱:GetBinaryFile /// 功能:返回服務器上的一個文件對象的二進制字節數組。 /// </summary> [WebService(Namespace="http://xml.sz.luohuedu.net/", Description="在Web Services裏利用.NET框架進行傳遞二進制文件。")] public class GetBinaryFile : System.Web.Services.WebService { #region Component Designer generated code //Web 服務設計器所必需的 private IContainer components = null; /// <summary> /// 清理所有正在使用的資源。 /// </summary> protected override void Dispose( bool disposing ) { if(disposing && components != null) { components.Dispose(); } base.Dispose(disposing); } #endregion public class Images: System.Web.Services.WebService { /// <summary> /// Web 服務提供的方法,返回給定文件的字節數組。 /// </summary> [WebMethod(Description="Web 服務提供的方法,返回給定文件的字節數組")] public byte[] GetImage(string requestFileName) { ///得到服務器端的一個圖片 ///如果你自己測試,注意修改下面的實際物理路徑 if(requestFileName == null || requestFileName == "") return getBinaryFile("D://Picture.JPG"); else return getBinaryFile("D://" + requestFileName); } /// <summary> /// getBinaryFile:返回所給文件路徑的字節數組。 /// </summary> /// <param name="filename"></param> /// <returns></returns> public byte[] getBinaryFile(string filename) { if(File.Exists(filename)) { try { ///打開現有文件以進行讀取。 FileStream s = File.OpenRead(filename); return ConvertStreamToByteBuffer(s); } catch(Exception e) { return new byte[0]; } } else { return new byte[0]; } } /// <summary> /// ConvertStreamToByteBuffer:把給定的文件流轉換爲二進制字節數組。 /// </summary> /// <param name="theStream"></param> /// <returns></returns> public byte[] ConvertStreamToByteBuffer(System.IO.Stream theStream) { int b1; System.IO.MemoryStream tempStream = new System.IO.MemoryStream(); while((b1=theStream.ReadByte())!=-1) { tempStream.WriteByte(((byte)b1)); } return tempStream.ToArray(); } [WebMethod(Description="Web 服務提供的方法,返回給定文件類型。")] public string GetImageType() { ///這裏只是測試,您可以根據實際的文件類型進行動態輸出 return "image/jpg"; } } } }

一旦我們創建了上面的asmx文件,進行編譯後,我們就可以編寫客戶端的代碼來進行調用這個Web Services了。

我們先“添加Web引用”,輸入:http://localhost/aspxWebCS/GetBinaryFile.asmx。下面,我們編寫顯示文件的中間文件:GetBinaryFileShow.aspx,這裏,我們只需要在後代碼裏編寫代碼即可,GetBinaryFileShow.aspx.cs文件內容如下:

using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.Web.Services; namespace aspxWebCS { /// <summary> /// GetBinaryFileShow 的摘要說明。 /// </summary> public class GetBinaryFileShow : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { // 在此處放置用戶代碼以初始化頁面 ///定義並初始化文件對象; xml.sz.luohuedu.net.aspxWebCS.GetBinaryFile.Images oImage; oImage = new xml.sz.luohuedu.net.aspxWebCS.GetBinaryFile.Images(); ///得到二進制文件字節數組; byte[] image = oImage.GetImage(""); ///轉換爲支持存儲區爲內存的流 System.IO.MemoryStream memStream = new System.IO.MemoryStream(image); ///定義並實例化Bitmap對象 Bitmap bm = new Bitmap(memStream); ///根據不同的條件進行輸出或者下載; Response.Clear(); ///如果請求字符串指定下載,就下載該文件; ///否則,就顯示在瀏覽器中。 if(Request.QueryString["Download"]=="1") { Response.Buffer = true; Response.ContentType = "application/octet-stream"; ///這裏下載輸出的文件名字 ok.jpg 爲例子,你實際中可以根據情況動態決定。 Response.AddHeader("Content-Disposition","attachment;filename=ok.jpg"); } else Response.ContentType = oImage.GetImageType(); Response.BinaryWrite(image); Response.End(); } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN:該調用是 ASP.NET Web 窗體設計器所必需的。 // InitializeComponent(); base.OnInit(e); } /// <summary> /// 設計器支持所需的方法 - 不要使用代碼編輯器修改 /// 此方法的內容。 /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion } }

最後,我們就編寫最終的瀏覽頁面:GetBinaryFile.aspx,這個文件很簡單,只需要aspx文件即可,內容如下:

<%@ Page language="c#" Codebehind="GetBinaryFile.aspx.cs" AutoEventWireup="false" Inherits="aspxWebCS.GetBinaryFile" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <HTML> <HEAD> <title>通過Web Services顯示和下載文件</title> <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0"> <meta name="CODE_LANGUAGE" Content="C#"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="GetBinaryFile" method="post" runat="server"> <FONT face="宋體"> <asp:HyperLink id="HyperLink1" NavigateUrl="GetBinaryFileShow.aspx?Download=1" runat="server">下載文件</asp:HyperLink> <br/> <!--下面是直接顯示文件--> <asp:Image id="Image1" ImageUrl="GetBinaryFileShow.aspx" runat="server"></asp:Image> </FONT> </form> </body> </HTML>

二:通過Web Services上載文件

向服務器上載文件可能有許多種方法,在利用Web Services上載文件的方法中,下面的這個方法應該是最簡單的了。我們仍象前面的例子那樣,首先建立Upload.asmx文件,其Upload.asmx.cs內容如下,裏面已經做了註釋:

using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; using System.IO; namespace xml.sz.luohuedu.net.aspxWebCS { /// <summary> /// Upload 的摘要說明。 /// </summary> [WebService(Namespace="http://xml.sz.luohuedu.net/", Description="在Web Services裏利用.NET框架進上載文件。")] public class Upload : System.Web.Services.WebService { public Upload() { //CODEGEN:該調用是 ASP.NET Web 服務設計器所必需的 InitializeComponent(); } #region Component Designer generated code //Web 服務設計器所必需的 private IContainer components = null; /// <summary> /// 設計器支持所需的方法 - 不要使用代碼編輯器修改 /// 此方法的內容。 /// </summary> private void InitializeComponent() { } /// <summary> /// 清理所有正在使用的資源。 /// </summary> protected override void Dispose( bool disposing ) { if(disposing && components != null) { components.Dispose(); } base.Dispose(disposing); } #endregion [WebMethod(Description="Web 服務提供的方法,返回是否文件上載成功與否。")] public string UploadFile(byte[] fs,string FileName) { try { ///定義並實例化一個內存流,以存放提交上來的字節數組。 MemoryStream m = new MemoryStream(fs); ///定義實際文件對象,保存上載的文件。 FileStream f = new FileStream(Server.MapPath(".") + "//" + FileName, FileMode.Create); ///把內內存裏的數據寫入物理文件 m.WriteTo(f); m.Close(); f.Close(); f = null; m = null; return "文件已經上傳成功。"; } catch(Exception ex) { return ex.Message; } } } }

要上載文件,必須提供一個表單,來供用戶進行文件的選擇,下面我們就建立這樣一個頁面Upload.aspx,用來提供文件上載:

<%@ Page language="c#" Codebehind="Upload.aspx.cs" AutoEventWireup="false" Inherits="aspxWebCS.Upload" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>通過Web Services上載文件</title> <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.0"> <meta name="CODE_LANGUAGE" content="Visual Basic 7.0"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server" enctype="multipart/form-data"> <INPUT id="MyFile" type="file" runat="server"> <br> <br> <asp:Button id="Button1" runat="server" Text="上載文件"></asp:Button> </form> </body> </HTML>

我們要進行處理的是在後代碼裏面,下面詳細的介紹,Upload.aspx.cs:

using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.Web.Services; using System.IO; namespace aspxWebCS { /// <summary> /// Upload 的摘要說明。 /// 利用該方法通過Web Services上載文件 /// </summary> public class Upload : System.Web.UI.Page { protected System.Web.UI.HtmlControls.HtmlInputFile MyFile; protected System.Web.UI.WebControls.Button Button1; private void Page_Load(object sender, System.EventArgs e) { // 在此處放置用戶代碼以初始化頁面 } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN:該調用是 ASP.NET Web 窗體設計器所必需的。 // InitializeComponent(); base.OnInit(e); } /// <summary> /// 設計器支持所需的方法 - 不要使用代碼編輯器修改 /// 此方法的內容。 /// </summary> private void InitializeComponent() { this.Button1.Click += new System.EventHandler(this.Button1_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void Button1_Click(object sender, System.EventArgs e) { ///首先得到上載文件信息和文件流 if(MyFile.PostedFile != null) { System.Web.HttpFileCollection oFiles; oFiles = System.Web.HttpContext.Current.Request.Files; if(oFiles.Count < 1) { Response.Write ("請選擇文件。"); Response.End(); } string FilePath = oFiles[0].FileName; if(FilePath == "" || FilePath == null) { Response.Write ("請選擇一個文件。"); Response.End(); } string FileName = FilePath.Substring(FilePath.LastIndexOf("//")+1); try { ///處理上載的文件流信息。 byte[] b = new byte[oFiles[0].ContentLength]; System.IO.Stream fs; xml.sz.luohuedu.net.aspxWebCS.Upload o; o = new xml.sz.luohuedu.net.aspxWebCS.Upload(); fs = (System.IO.Stream)oFiles[0].InputStream; fs.Read(b, 0, oFiles[0].ContentLength); ///調用Web Services的UploadFile方法進行上載文件。 Response.Write(o.UploadFile(b, FileName)); fs.Close(); } catch(Exception ex) { Response.Write(ex.Message); } } else { Response.Write("請選擇文件"); } } } }

最後,需要注意的是:在保存文件時,您應該確保指定文件的完整路徑(例如,"C:/MyFiles/Picture.jpg"),並確保爲 ASP.NET 使用的帳戶提供要存儲文件的目錄的寫權限。上載大文件時,可使用 元素的 maxRequestLength 屬性來增加文件大小的最大允許值,例如:

<configuration> <system.web> <httpRuntime maxRequestLength="1048576" executionTimeout="3600" /> </system.web> </configuration>

其中:maxRequestLength:指示 ASP.NET 支持的HTTP方式上載的最大字節數。該限制可用於防止因用戶將大量文件傳遞到該服務器而導致的拒絕服務攻擊。指定的大小以 KB 爲單位。默認值爲 4096 KB (4 MB)。executionTimeout:指示在被 ASP.NET 自動關閉前,允許執行請求的最大秒數。在當文件超出指定的大小時,如果瀏覽器中會產生 DNS 錯誤或者出現服務不可得到的情況,也請修改以上的配置,把配置數加大。

另外,上載大文件時,還可能會收到以下錯誤信息:

aspnet_wp.exe (PID: 1520) 被回收,因爲內存消耗超過了 460 MB(可用 RAM 的百分之 60)。

如果遇到此錯誤信息,請增加應用程序的 Web.config 文件的 元素中 memoryLimit 屬性的值。例如:

<configuration> <system.web> <processModel memoryLimit="80"/> </system.web> </configuration>

我在自己的機器上測試,可以上傳50M以上的文件。以上代碼在Windows XP + .NET 1.0 + VS.NET2002下測試通過。

 

http://dotnet.aspx.cc/article/6381bd5f-51f3-4339-4239-1328564a1b2a/read.aspx

發佈了87 篇原創文章 · 獲贊 6 · 訪問量 64萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章