欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

HTTP协议下用Web Service上传大文件的解决方案

程序员文章站 2022-06-14 11:39:03
用http协议上传大文件也许是个不好办的问题。主要是它的不连续性,使得上传文件感觉很“危险”。特别是很大的文件(几百mb甚至是上g的文件),心里总觉得不踏实,一不小心就会出...
用http协议上传大文件也许是个不好办的问题。主要是它的不连续性,使得上传文件感觉很“危险”。特别是很大的文件(几百mb甚至是上g的文件),心里总觉得不踏实,一不小心就会出现问题,而一但出现问题就无法继续上传,这是很郁闷的。

后来在一些网站上找到一些上传文件的组件,但都是要用到一些com组件。至于后来的asp.net下上传大文件的解决方案,我也做过一个组件,后来发现根本就不用自己写什么组件,利用asp.net自己的上传方法也可以解决大文件上传,真是郁闷的要死了。。。。

回想之后,决定用web service来做一个文件上传,还是利用http协议,这样不用在服务器上做太多的变动,而客户端也简单。

首先是解决方案的设计:因为web service可以利用soap来传递数据,而且可以传递十进制数据,因此可以想到,在服务上公开一个方法,参数可以是byte数组,这样可以把文件分块的上传到服务器。这一解决方法我做过,但速度很慢。后来在ms上找到一些文章,用ms最新公开的服务组件上传文件,速度快了很多。而自己所要做的就是组织一些安全性的问题。

部份代码:upload instance

复制代码 代码如下:

using system; 
using system.io; 
using microsoft.web.services2; 
using microsoft.web.services2.dime; 

namespace webb.wave.winupload 

/**//// <summary> 
/// summary description for controls. 
/// </summary> 
public class uploadinstance2 

fields#region fields 
private string m_guid; 
private datetime m_uploadtime; 
private long m_filelength; 
private long m_currentpoint; 
private string m_pathonserver; 
private long m_userid; 
#endregion 

properties#region properties 
public long userid 

get{return this.m_userid;} 
set{this.m_userid=value;} 

public string guid 

get{return this.m_guid;} 
set{this.m_guid=value;} 

public datetime uploadtime 

get{return this.m_uploadtime;} 
set{} 

public long filelength 

get{return this.m_filelength;} 
set{this.m_filelength=value;} 

public long currentpoing 

get{return this.m_currentpoint;} 
set{this.m_currentpoint=value;} 

public string pathonserver 

get{return this.m_pathonserver;} 
set{this.m_pathonserver=value;} 

public string fullpathonserver 

get 

if(this.m_guid!=string.empty&&this.m_pathonserver!=string.empty) 

return path.combine(this.m_pathonserver,this.m_guid+".rem"); 

else 

return string.empty; 



public string filename 

get 

if(this.m_guid!=string.empty) 

return this.m_guid+".rem"; 

else 

return string.empty; 




#endregion 

public uploadinstance2() 

this.m_guid = system.guid.newguid().tostring(); 
this.m_uploadtime = system.datetime.now; 
this.m_currentpoint = 0; 
this.m_filelength = 0; 
this.m_pathonserver = string.empty; 

public uploadinstance2(string i_path,string i_guid,long i_filelength) 

string m_fullpath = path.combine(i_path,i_guid); 
if(!file.exists(m_fullpath)) return; 
this.m_guid = i_guid; 
this.m_uploadtime = system.datetime.now; 
this.m_pathonserver = i_path; 
fileinfo m_fileinfo = new fileinfo(m_fullpath); 
this.m_currentpoint = m_fileinfo.length; 
this.m_filelength = i_filelength; 


public bool uploaddata(byte[] i_data, long i_currentpoint, int i_datasize) 

string m_fullpath = this.fullpathonserver; 
if(!file.exists(m_fullpath)&&this.m_currentpoint!=0)return false; 
long m_filepoint = new fileinfo(m_fullpath).length; 
if(m_filepoint!=i_currentpoint) return false; 
filestream m_filestream = new filestream(m_fullpath,filemode.append); 
m_filestream.write(i_data,0,i_datasize); 
m_filestream.close(); 
return true; 


public void abandantupload() 

string m_fullpath = this.fullpathonserver; 
try{file.delete(m_fullpath);} 
catch{} 


public void createfile() 

string m_fullpath = this.fullpathonserver; 
if(!file.exists(m_fullpath)) 

file.create(m_fullpath).close(); 

else 

try 

file.delete(m_fullpath); 
}catch{} 
file.create(m_fullpath).close(); 





上传过程:
复制代码 代码如下:

#region uploadprocess 
public void uploadprocess() 

datetime m_start = datetime.now; 
this.textbox_outmsg.appendtext("initialize upload\r\n"); 
if(this.m_upload==null||this.m_uploadguid==null||this.m_uploadguid==string.empty) 
{  
this.textbox_outmsg.appendtext("upload instance id error or login to the server faild\r\n"); 
this.textbox_outmsg.appendtext("upload faild.\r\n"); 
return; 

this.textbox_outmsg.appendtext("open file\r\n"); 
if(this.m_filepath==null||this.m_filepath==string.empty||!file.exists(this.m_filepath)) 

this.textbox_outmsg.appendtext("open file error\r\n"); 
this.textbox_outmsg.appendtext("upload faild.\r\n"); 
return; 

fileinfo m_fileinfo = new fileinfo(this.m_filepath); 
filestream m_fs = new filestream(this.m_filepath, filemode.open, fileaccess.read); 
this.textbox_outmsg.appendtext("start upload file\r\n"); 
int m_buffer = 10; //kbytes 
long m_currentpoint = 0; 
long m_filelength = m_fileinfo.length; 
bool m_uploadresult = false; 
byte[] m_data = new byte[m_buffer*1024]; 
long m_readbytes = m_fs.read(m_data, 0, m_buffer*1024); 
this.uploadprocessbar.maximum = 100; 
this.uploadprocessbar.minimum = 0; 
while(m_readbytes>0) 

memorystream m_memorystream = new memorystream(m_data, 0,(int)m_readbytes); 
dimeattachment dimeattach = new dimeattachment("image/gif", typeformat.mediatype, m_memorystream); 
this.m_upload.requestsoapcontext.attachments.add(dimeattach); 
m_uploadresult = this.m_upload.uploadfiledata(this.m_uploadinstance,m_currentpoint,m_readbytes); 
if(m_uploadresult) 

m_currentpoint +=m_readbytes; 
m_readbytes = m_fs.read(m_data,0,m_buffer*1024); 
// this.textbox_outmsg.appendtext("uploading:"+m_currentpoint.tostring()+"/"+m_filelength.tostring()+"\r\n"); 
this.uploadprocessbar.value = (int)(m_currentpoint*100/m_filelength); 
this.label_outpercent.text = this.uploadprocessbar.value.tostring()+"%"; 

else 

this.textbox_outmsg.appendtext("upload file error.\r\n"); 
m_fs.close(); 
this.m_upload.abandantupload(this.m_uploadinstance); 
return; 


this.textbox_outmsg.appendtext("file upload finished.\r\n"); 
this.button_cancel.enabled = false; 
m_fs.close(); 
this.resetform(); 

#endregion 


测试项目代码:
http://test.0579fw.com/myfile/kiyeer/客户上传/webbwinupload.zip

出现错误的解决方法:
*****************************************************

 引用内容
error 1 'winformtest.localhost.webbwinupload' does not contain a definition for 'requestsoapcontext' d:\webbwinupload\winformtest\webbwinupload.cs 448 19 winformtest 

当你更新web引用的时候,.net自动生成的web引用为: 
public class webbwinupload : system.web.services.protocols.soaphttpclientprotocol 
请转化为: 
public class webbwinupload : microsoft.web.services2.webservicesclientprotocol 
查找引用下自动生成的c#文件reference.cs