十年風雨路 · 一心鑄精品

接一個官網 留一件精品 做一個項目 樹一塊樣板

asp.net下實現支持文件分塊多點異步上傳的 Web Services

本文的客戶端應用程序不包括 ASP.Net Web 應用程序! 本文假設 URL: http://localhost/mywebservices/updownload.asmx 共有 4 個程序文件 (Web.Config 就不贅述了) Server Side: 標題中所提到的 "異步" 其實在服務器端的程序并沒有什么特殊的,而主要是通過客戶端應用程序 異步調用相關 Web Method 實現的! 1. updownload.asmx ,位于 IIS 的某個 Web 共享目錄,代碼如下,只有一句話:

時間:2013年01月15日 點擊量:
本文的客戶端應用程序不包括 ASP.Net web 應用程序!

本文假設 URL: http://localhost/mywebservices/updownload.asmx

共有 4 個程序文件 (Web.Config 就不贅述了)

Server Side:

標題中所提到的 "異步" 其實在服務器端的程序并沒有什么特殊的,而主要是通過客戶端應用程序
異步調用相關 Web Method 實現的!

1. updownload.asmx ,位于 IIS 的某個 Web 共享目錄,代碼如下,只有一句話:

<%@ WebService Language="c#" Codebehind="UpDownLoad.asmx.cs" Class="Service1" %>

2. updownload.asmx.cs ,即: updownload.asmx 的 Codebehind ,位于 IIS 的某個 Web 共享目錄的 bin 子目錄下,代碼如下:

/*

本文件位于 Web 共享目錄的 bin 子目錄下,通過執行如下命令行編譯:
csc /t:library updownload.asmx.cs

*/
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.IO;
using System;

public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}

//從 Web Method 本身,其實看不出 "同步" 還是 "異步"
[WebMethod(Description = "為了支持多點分塊異步上傳文件,此方法必須由客戶端預先調用,以便在服務器端生成指定 FileName 和 Length 大小的空白文件預定空間! 建議客戶端同步調用")]
public string CreateBlankFile(string FileName,int Length) //建議由客戶端同步調用
{
FileStream fs = new FileStream(Server.MapPath(".") + "\\" + FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
fs.Write(new byte[Length], 0, Length);
fs.Close();
fs = null;
return FileName + " (" + Length + ") 空白文件已經創建!";
}

[WebMethod(Description = "提供一個用于一次完整上傳整個文件的方法! 建議客戶端同步調用")]
public string UploadFileBytes(byte[] Bytes,string FileName)
{
return UploadFileChunkBytes(Bytes, 0, FileName);
}

[WebMethod(Description = "提供一個用于一次只上傳由 Position 位置起始的, Bytes 字節的 FileName 文件塊存入服務器端相應文件的相應字節位置! 建議客戶端異步調用")]
// 這里只要多提供一個 Position 參數,余下的再由客戶端調用異步的該方法,就輕松達到目的了!
public string UploadFileChunkBytes(byte[] Bytes,int Position,string FileName)
{
try
{
FileStream fs = new FileStream(Server.MapPath(".") + "\\" + FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
//該 Bytes 的字節要寫到 服務器端 相應文件的從 Position 開始的字節
fs.Position = Position;
fs.Write(Bytes, 0, Bytes.Length);
fs.Close();
fs = null;
return FileName + " 文件塊: 位置[" + Position + "," + (Position + Bytes.Length) + "] 大小(" + Bytes.Length + ") 上傳成功!";
}
catch (Exception e)
{
return e.Message;
}
}

[WebMethod]
public byte[] DownloadFileBytes(string FileName)
{
if (File.Exists(FileName))
{
try
{
FileStream fs = File.OpenRead(FileName);
int i = (int) fs.Length;
byte[] ba = new byte[i];
fs.Read(ba,0,i);
fs.Close();
return ba;
}
catch
{
return new byte[0];
}
}
else
{
return new byte[0];
}
}
}


//=======================================================================

Client Side:
3. UpDownloadProxy.cs :
本文件由如下命令生成
% Visual Studio .Net 2003 安裝目錄下的 %\SDK\v1.1\Bin\wsdl.exe
具體命令行如下:
wsdl.exe /l:CS /out:UpDownloadProxy.cs http://localhost/MyWebServices/updownload.asmx?wsdl
生成的本地的客戶端代理類代碼里已經為每個 Web Method 生成了可異步和同步執行的方法,例如:
public string HelloWorld() {}
public System.IAsyncResult BeginHelloWorld(...) {}
public string EndHelloWorld(...) {}

下面是該命令行生成的完整的 UpDownloadProxy.cs 代碼,就不修改了:
/*

通過執行如下命令行編譯,生成 UpDownloadProxy.dll :
csc /t:library UpDownloadProxy.cs

*/

//------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Runtime Version: 1.1.4322.573
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
//------------------------------------------------------------------------------

//
// 此源代碼由 wsdl, Version=1.1.4322.573 自動生成。
//
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Services;


/// <remarks/>
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="Service1Soap", Namespace="http://tempuri.org/")]
public class Service1 : System.Web.Services.Protocols.SoapHttpClientProtocol {

/// <remarks/>
public Service1() {
this.Url = "http://localhost/MyWebServices/updownload.asmx";
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string HelloWorld() {
object[] results = this.Invoke("HelloWorld", new object[0]);
return ((string)(results[0]));
}

/// <remarks/>
public System.IAsyncResult BeginHelloWorld(System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("HelloWorld", new object[0], callback, asyncState);
}

/// <remarks/>
public string EndHelloWorld(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((string)(results[0]));
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CreateBlankFile", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string CreateBlankFile(string FileName, int Length) {
object[] results = this.Invoke("CreateBlankFile", new object[] {
FileName,
Length});
return ((string)(results[0]));
}

/// <remarks/>
public System.IAsyncResult BeginCreateBlankFile(string FileName, int Length, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("CreateBlankFile", new object[] {
FileName,
Length}, callback, asyncState);
}

/// <remarks/>
public string EndCreateBlankFile(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((string)(results[0]));
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/UploadFileBytes", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string UploadFileBytes([System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] System.Byte[] Bytes, string FileName) {
object[] results = this.Invoke("UploadFileBytes", new object[] {
Bytes,
FileName});
return ((string)(results[0]));
}

/// <remarks/>
public System.IAsyncResult BeginUploadFileBytes(System.Byte[] Bytes, string FileName, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("UploadFileBytes", new object[] {
Bytes,
FileName}, callback, asyncState);
}

/// <remarks/>
public string EndUploadFileBytes(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((string)(results[0]));
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/UploadFileChunkBytes", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string UploadFileChunkBytes([System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] System.Byte[] Bytes, int Position, string FileName) {
object[] results = this.Invoke("UploadFileChunkBytes", new object[] {
Bytes,
Position,
FileName});
return ((string)(results[0]));
}

/// <remarks/>
public System.IAsyncResult BeginUploadFileChunkBytes(System.Byte[] Bytes, int Position, string FileName, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("UploadFileChunkBytes", new object[] {
Bytes,
Position,
FileName}, callback, asyncState);
}

/// <remarks/>
public string EndUploadFileChunkBytes(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((string)(results[0]));
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DownloadFileBytes", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")]
public System.Byte[] DownloadFileBytes(string FileName) {
object[] results = this.Invoke("DownloadFileBytes", new object[] {
FileName});
return ((System.Byte[])(results[0]));
}

/// <remarks/>
public System.IAsyncResult BeginDownloadFileBytes(string FileName, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("DownloadFileBytes", new object[] {
FileName}, callback, asyncState);
}

/// <remarks/>
public System.Byte[] EndDownloadFileBytes(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((System.Byte[])(results[0]));
}
}

//=======================================================================
4. UpDownloadClient.cs :
該程序才是真正實現文件分塊多點異步上傳的核心代碼:

/*

通過執行如下命令行編譯:
csc updownloadClient.cs /r:updownloadproxy.dll

*/
using System;
using System.IO;

public class Class1
{
static void Main(string[] args)
{
//Download(ServerSidepath, ClientSidePath)
Download(@"e:\test.jpg", @"f:\test_local.jpg");
System.Console.WriteLine("down End");

System.Console.WriteLine("同步 up file exec ...");
UploadFile(@"e:\Northwind.mdb");
System.Console.WriteLine("同步 up file End\n");

System.Console.WriteLine("異步 up chunks exec ...");
UploadFileChunks(@"e:\test.rar", 64);
System.Console.ReadLine();
}

public static void UploadFile(string LocalFileName)
{
Service1 xx = new Service1();
FileStream fs = new FileStream(LocalFileName, FileMode.Open); //Client Side Path
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
//調用 "同步執行" 的本地 Web Sevices 代理類的 方法,相當于同步調用了 Web Method !
xx.UploadFileBytes(buffer, System.IO.Path.GetFileName(LocalFileName));
}

//指定要上傳的本地文件的路徑,及每次上傳文件塊的大小
public static void UploadFileChunks(string LocalFileName,int ChunkSize)
{
Service1 xx = new Service1();
string filename = System.IO.Path.GetFileName(LocalFileName);

FileStream fs = new FileStream(LocalFileName, FileMode.Open); //Client Side Path
//fs = File.OpenRead(LocalFileName);

int r = (int) fs.Length; //用于記錄剩余還未上傳的字節數,初值是文件的大小

//調用 "同步執行" 的本地 Web Sevices 代理類的 方法,相當于同步調用了 Web Method !
//預定服務器端空間
xx.CreateBlankFile(filename,r);
int size = ChunkSize * 1024;
int k = 0; //用于記錄已經上傳的字節數
i++; //用于記錄上傳的文件塊數
while (r >= size)
{
byte[] buffer = new byte[size];
fs.Read(buffer,0,buffer.Length);
//調用 "異步執行" 的本地 Web Sevices 代理類的 方法,相當于異步調用了 Web Method !
//該 buffer 的字節要寫到 服務器端 相應文件的從 Position = k 開始的字節
xx.BeginUploadFileChunkBytes(buffer,k,filename,new AsyncCallback(UploadFileChunkCallback),xx);
k += size;
r -= size;
i++;
}
if (r > 0) //剩余的零頭
{
byte[] buffer = new byte[r];
fs.Read(buffer,0,buffer.Length);
//調用 "異步執行" 的本地 Web Sevices 代理類的 方法,相當于異步調用了 Web Method !
//該 buffer 的字節要寫到 服務器端 相應文件的從 Position = k 開始的字節
xx.BeginUploadFileChunkBytes(buffer,k,filename,new AsyncCallback(UploadFileChunkCallback),xx);
i++;
}
fs.Close();

}

private static int i = -1; //用于記錄上傳的文件塊數

private static void UploadFileChunkCallback(IAsyncResult ar)
{
Service1 x = (Service1) ar.AsyncState;
Console.WriteLine(x.EndUploadFileChunkBytes(ar));
if ( --i == 0)
{
Console.WriteLine("異步 up all chunks end");
}
}

public static void Download(string ServerSideFileName,string LocalFileName)
{
Service1 xx = new Service1();
byte[] ba = xx.DownloadFileBytes(ServerSideFileName); //Server Side Path

FileStream fs = new FileStream(LocalFileName, FileMode.Create); //Client Side Path
fs.Write(ba,0,ba.Length);
fs.Close();
}
}


//===========================================================================
至此我們通過純手工的方式完成了任務,之所以不用 VS 就是為了讓碼子簡潔明了!
Microshaoft .Night 就是這么平易近人! (PMPMP to MS)
通過 Web Sevices 上傳文件非常簡單,甚至比傳統的 http Web 上傳還簡單!
同時較輕松地就實現了文件分塊多點異步上傳:
Server 端代碼沒啥特殊的!
Client 端代碼稍微復雜些!

推薦案例

  • 成都森美啦園林綠化工程公

  • 四川尚恒科技有限公司

  • 成都九邦物流有限責任公司

  • 四川品睿餐飲管理有限公司

  • 美繪陶社陶藝手繪工作室-暖

  • 成都恩多施生物工程技術有

  • 汶川羌人土特產有限公司

  • 印刷設計公司網站No.3138

聯系我們 / CONTACT US

  • 四川省成都市金牛區五福橋東路229號龍湖北城天街28棟903室
  • 服務熱線:400-000-2367 028-86088588
  • 總機:028-62322623-0
  • 傳真:028-62322623-823

掃碼訪問冠辰手機網站

版權所有 Copyright © 2002-2019 四川冠辰科技開發有限公司  www.mtlum.tw 保留所有權利  蜀ICP備11012605號

地址:四川省成都市金牛區五福橋東路229號龍湖北城天街28棟903室

服務熱線:400-000-2367 028-86088588 總機:028-62322623-0 傳真:028-62322623-823

捕鱼王游戏机 澳洲幸运5彩票开奖结果查询 零点棋牌安卓版 手机游戏赌博赚钱 江苏快3下载官网 腾讯棋牌欢乐斗地主不洗牌 排列五没有开出的号码查询 足球专家推荐 晓游棋牌更新版本 微信捕鱼可以微信提现金 细数那些最靠谱阅读能够赚钱的 广东好彩1 大富豪棋牌娱乐官网 网上彩票合买是真的 007之大战皇家赌场 秒速时时彩规律 彩乐乐群 澳洲幸运5彩票开奖结果查询 零点棋牌安卓版 手机游戏赌博赚钱 江苏快3下载官网 腾讯棋牌欢乐斗地主不洗牌 排列五没有开出的号码查询 足球专家推荐 晓游棋牌更新版本 微信捕鱼可以微信提现金 细数那些最靠谱阅读能够赚钱的 广东好彩1 大富豪棋牌娱乐官网 网上彩票合买是真的 007之大战皇家赌场 秒速时时彩规律 彩乐乐群