源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

asp.net下实现支持文件分块多点异步上传的 Web Services

  • 时间:2022-03-30 01:45 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要: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 共享目录,代码如下,只有一句话: <%@ 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 端代码稍微复杂些!
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部