asp.net下实现支持文件分块多点异步上传的 Web Services
程序员文章站
2023-11-11 20:49:28
本文的客户端应用程序不包括 asp.net web 应用程序! 本文假设 url: http://localhost/my...
本文的客户端应用程序不包括 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 端代码稍微复杂些!
本文假设 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 端代码稍微复杂些!