浏览主题:??????????????网招???京京???网招???
主题:??????????????网招???京京???网招???
|
c# 程序代码 using System; using System.Collections.Generic; using System.Text; using System.Web; namespace DEVMS.COM.DMForum.Kernel { /// <summary> /// 二进制数据读取控制。 /// </summary> //一个boundary条分隔一个文件/表单数据,每次依次取一字节数据,取到换行时结束,随后判断此行 //每次遇到boundary行即是开始新数据表单 public class HttpBinaryReader { private string _boundary; private string _tempdirectory; private string _hash; private int _index; private CheckAccessDelegate _cad; private HttpWorkerRequest _request; /// <summary> /// 初始化二进制数据读取控制。 /// </summary> public HttpBinaryReader() { } /// <summary> /// 初始化二进制数据读取控制。 /// </summary> /// <param name="boundary">分隔块字符串值。</param> public HttpBinaryReader( string boundary, string tempdirectory, string hash,CheckAccessDelegate cad,HttpWorkerRequest request ) { this._boundary = boundary; this._tempdirectory = tempdirectory; this._hash = hash; this._cad = cad; this._request = request; } public string getString( byte[] b ) { string t = DEVMS.COM.API.BaseObject.String( b ); if ( t.Length < 2 ) return t; t = t.Substring( 1 ); return t.Substring( 0, t.Length - 1 ); } public void output( string mess ) { System.Web.HttpContext.Current.Response.Write( mess + "<br/>" ); System.Web.HttpContext.Current.Response.Flush(); } /// <summary> /// 读取每段数据的头信息,返回除头信息外的数据正文。 /// </summary> /// <returns></returns> public string ReadBlockHead( string data, HttpBlockInfo hbinfo ) { string t = data; int ts = t.IndexOf( "\r\nContent-Disposition: form-data;" ) + "\r\nContent-Disposition: form-data;".Length; //获取第一行头信息文本 string cdt = t.Substring( ts ); string scdt = cdt.Substring( 0, cdt.IndexOf( "\r\n" ) ); //按;号分隔 string[] cds = scdt.Split( ";".ToCharArray() ); //遍历每项 foreach ( string cd in cds ) { //分开=号两旁的名称和值 string[] cs = cd.Split( "=".ToCharArray() ); //如果不是键=值形式则跳到下一项 if ( cs.Length < 2 ) continue; //如果键名是name,那么代表此项是表单域名称,将值赋予块信息对象的表单域名称属性 if ( cs[0].Trim() == "name" ) { hbinfo.InputName = cs[1].Trim().Replace( "\"", "" ); } //如果键名不是name,那么则判断此项是文件域附加原文件路径信息,将值赋予块信息对象的源文件路径属性 //同时,则证明此段数据是文件数据,那么应将当前系统文件索引递增1。以区别上一文件数据。 else { hbinfo.SourceFile = cs[1].Trim().Replace("\"",""); this._index += 1; } } //将第一行后的字符进行处理 //取得第二行的数据 cdt = cdt.Substring( cdt.IndexOf( "\r\n" ) + 2 ); scdt = cdt.Substring( 0, cdt.IndexOf( "\r\n" ) ); //按:号分开 cds = scdt.Split( ":".ToCharArray() ); //如果不是键:值形式或者键名不等于Content-Type的话,则认为此段没有第二信息行,则直接跳过一个回车换行后将指针置于正文数据头 if ( cds.Length == 2 && cds[0] == "Content-Type" ) { //如果是键:值形式以及键名等于Content-Type的话,则读取它的值并赋值给块信息对象的数据流内容类型属性,然后跳过两个回车换行后将指针置于正文数据头 hbinfo.ContentType = cds[1].Trim(); cdt = cdt.Substring( cdt.IndexOf( "\r\n\r\n" ) + 4 ); } else { cdt = cdt.Substring( cdt.IndexOf( "\r\n" ) + 2 ); } //此时的cdt即正文数据的string表现形式,把它返回 return cdt; } public byte[] copy( byte[] data, int index, int count ) { byte[] b = new byte[count]; if ( index + count > data.Length ) return b; for ( int i = index; i < index + count; i++ ) { b[i - index] = data[i]; } return b; } public bool comBytes( byte[] d1, byte[] d2 ) { if ( d1.Length != d2.Length ) return false; for ( int i = 0; i < d1.Length; i++ ) { if ( d1[i] != d2[i] ) return false; } return true; } public int indexOfBytes( string str, byte[] data ) { byte[] s = System.Text.Encoding.Default.GetBytes( str ); for ( int i = 0; i < data.Length; i++ ) { if ( data[i] == s[0] ) { byte[] temp = copy( data, i, s.Length ); if ( comBytes( temp, s ) ) { return i; } } } return -1; } public string getstr( byte[] b ) { return DEVMS.COM.API.BaseObject.String( b ); } public byte[] ReadFile( ref byte[] data ) { int s = indexOfBytes( "--" + this._boundary, data ); if ( s < 0 ) return data; byte[] b; byte[] c; if ( s > 0 ) { b = copy( data, 0, s ); c = copy( data, s, data.Length - s ); } else { byte[] t = copy( data, s + ( "--" + this._boundary ).Length, data.Length - s - ( "--" + this._boundary ).Length ); s = indexOfBytes( "--" + this._boundary, t ); if ( s < 0 ) s = t.Length; b = copy( t, 0, s ); c = copy( t, s, t.Length - s ); } s = indexOfBytes( "\r\nContent-Type:", b ); if ( s > 0 ) { s = indexOfBytes( "\r\n\r\n", b ); if ( s > 0 ) { return copy( b, s + 4, b.Length - s - 4 ); } } else { if ( indexOfBytes( "\r\nContent-Disposition: form-data;", b ) >= 0 ) { b = ReadFile( ref c ); } } return b; } public string ReadNextBlock( byte[] data, List<HttpBlockInfo> list, string tempfile,bool end ) { //按分隔符分开每段数据 byte[] c = data; string temp = DEVMS.COM.API.BaseObject.String( data ); string[] temps = temp.Split( new string[] { "--" + this._boundary }, StringSplitOptions.RemoveEmptyEntries ); //定义当前文件流对象和块信息对象 System.IO.FileStream stream = null; HttpBlockInfo hbinfo = null; string tmpfile = string.Empty; //分析每一段数据 foreach ( string tmp in temps ) { //将当前数据段数据保存在一个局部变量 string t = tmp; //将字节数组形式的数据保存在另一个局部变量 byte[] tb = DEVMS.COM.API.BaseObject.Bytes( t ); if ( t == "--\r\n" ) { //全部数据段已经读取分析完毕,指针到了数据流最末尾,结束所有操作 return tempfile.Replace( "#N", this._index.ToString() ); } if ( t.IndexOf( "\r\nContent-Disposition: form-data;" ) == 0 ) { //此处为真则代表已经上一次读取已经完全读取了一整段数据,接下来的数据属于另一段了。 //创建一个新的块信息对象。 hbinfo = new HttpBlockInfo( string.Empty, string.Empty, string.Empty, string.Empty, string.Empty ); //调用头解析方法读取块信息并取得正文byte[]数据 string binstr = this.ReadBlockHead( t, hbinfo ); //调用类型检查函数检查类型合法型 this._cad( this._request, hbinfo, this._hash ); //标记线程运行标志 //HttpContext.Current.Application[this._hash] = "UploadThreadRuning"; //读取正文数据 byte[] bin = ReadFile( ref c ); //如果此块为文件数据,则添加数据到对应文件 if ( hbinfo.SourceFile.Length > 0 ) { //将全局文件序号递增1 this._index += 1; //初始化临时文件路径,文件序号以当前全局文件序号为准 tmpfile = tempfile.Replace( "#N", this._index.ToString() ); //将正文数据添加到文件中 stream = new System.IO.FileStream( tmpfile, System.IO.FileMode.Append ); if ( end ) { stream.Write( bin, 0, bin.Length - 2 ); } else { stream.Write( bin, 0, bin.Length ); } stream.Flush(); stream.Close(); stream.Dispose(); hbinfo.TempFile = tmpfile; } else { hbinfo.Value = binstr; } //将块信息对象添加到块信息列表中 & |