用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();
}
}
}
}
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();
}
}
}
}
上传过程:
UploadProcess
#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
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://www.cnblogs.com/Files/WuCountry/WebbWinUpload.zip
wan