一,文件夹
二,upLoad.cs是继承IHttpModule的类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text; using System.IO; using System.Reflection; using System.Globalization; using System.Web.Hosting; /// <summary> ///upLoad 的摘要说明 /// </summary> public class upLoad : IHttpModule { public void Init(HttpApplication application) { application.BeginRequest += new EventHandler(this.Application_BeginRequest); } #region 用户变量 private Encoding eContentEncode;//HTTP上下文的编码 private bool bReadDataFinished = true;//用于表示上一个文件是否读取完毕,是否可以开始新文件的读取 private HttpApplication app;//HttpApplication 类的一个实例在其生存期内被用于处理多个请求 private byte[] bboundary;//界限数组 如:“-----------------------------7d87d1cc0a88” private byte[] bendboundary; private byte[] brequest;//没有文件信息的HTTP请求上下文字节数组 private byte[] temp;//临时字节数组,用来存放上一次截取的一部分字节 // private int ufiFileInfo.strFileGuid;//子集数,用来给文件命名 #endregion void Application_BeginRequest(object sender, EventArgs e) { app = sender as HttpApplication; if (app == null) return; string ContentType = app.Request.ContentType;//类型共两种1(默认是application/x-www-form-urlencoded)上传是(multipart/form-data) //判断是否为上传文件类型 if (string.Compare(ContentType, 0, "multipart/form-data", 0, "multipart/form-data".Length, true) != 0) return; int iReadStepSize = 7600;//分块读取数据的大小 int iContentLength = app.Request.ContentLength;//文件总长度(不包括HTTP请求头) //声明一个具体的当前HTTP请求实例 IServiceProvider provider = (IServiceProvider)HttpContext.Current; HttpWorkerRequest request = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest)); eContentEncode = app.Request.ContentEncoding;//获取请求编码类型 byte[] bPreloadedEnitityBody = request.GetPreloadedEntityBody();//获取HTTP请求已经被读取的部分 bboundary = GetMultipartBoundary(app.Request.ContentType);//获取分界的数组(包含分界前的换行符) bendboundary = GetEndBoundary(app.Request.ContentType); temp = null; brequest = null; // ufiFileInfo.strFileGuid = 0; int iRead = request.GetPreloadedEntityBodyLength();//已经读取的字节数 string filename = null;//文件重命名 string sguid = GetUploadId(bPreloadedEnitityBody, eContentEncode); UploadFileInfo ufiFileInfo = (UploadFileInfo)HttpContext.Current.Cache[sguid]; ufiFileInfo.iTotalBytes = iContentLength; int iLeave = iContentLength - iRead;//剩余未读取的字节数 //将读取的数据写入缓冲区然后再写入文件 bool bGoOnGetFileFromThisByte = true; if (bReadDataFinished)//判断是否是第一次读取数据 { //判断是否有文件数据头 int iDataStart1 = 0, iDataStart2 = 0, iDataStart3 = 0, iEndStart = 0; //判断是否含有“filename=”字段 byte[] b1 = eContentEncode.GetBytes("filename="); int iStartIndex = 0, iEndIndex = bPreloadedEnitityBody.Length - 1; while (iStartIndex <= iEndIndex) { int i = -1;//判断是否找到完全匹配 iStartIndex = Array.IndexOf(bPreloadedEnitityBody, b1[0], iStartIndex + 1); //如果没有找到 if (iStartIndex < 0) { break; } for (int index = 1; index < b1.Length; index++) {//对剩余字节进行逐个匹配 if (iStartIndex + index > bPreloadedEnitityBody.Length - 1) {//超出范围 break; } if (bPreloadedEnitityBody[iStartIndex + index] != b1[index]) { //如果不匹配 break; } i = 0; } if (i == 0) { iDataStart1 = iStartIndex + 9; break; } } //获取\r\nContent-Type: text/plain byte[] b2 = eContentEncode.GetBytes("\r\n"); iStartIndex = iDataStart1; while (iStartIndex <= iEndIndex) { int i = -1; iStartIndex = Array.IndexOf(bPreloadedEnitityBody, b2[0], iStartIndex); if (iStartIndex < 0) { break; } for (int index = 1; index < b2.Length; index++) {//对剩余字节进行逐个匹配 if (iStartIndex + index > bPreloadedEnitityBody.Length - 1) {//超出范围 break; } if (bPreloadedEnitityBody[iStartIndex + index] != b2[index]) { //如果不匹配 break; } i = 0; } if (i == 0) { iDataStart2 = iStartIndex + 2; break; } } //获取文件开始处的位置 iStartIndex = iDataStart2; while (iStartIndex <= iEndIndex) { int i = -1; iStartIndex = Array.IndexOf(bPreloadedEnitityBody, b2[0], iStartIndex); if (iStartIndex < 0) { break; } for (int index = 1; index < b2.Length; index++) {//对剩余字节进行逐个匹配 if (iStartIndex + index > bPreloadedEnitityBody.Length - 1) {//超出范围 break; } if (bPreloadedEnitityBody[iStartIndex + index] != b2[index]) { //如果不匹配 break; } i = 0; } if (i == 0) { iDataStart3 = iStartIndex + 4;//因为有两个换行所以加4 break; } } //获取文件重命名filename int iStartTxtname = 0, iEndTxtname = 0; iStartIndex = 0; //获取name=“txtname”在数据头中的位置 byte[] txtname = eContentEncode.GetBytes("txtname\""); while (iStartIndex <= iEndIndex) { int i = -1; iStartIndex = Array.IndexOf(bPreloadedEnitityBody, txtname[0], iStartIndex + 1); if (iStartIndex < 0) { break; } for (int index = 1; index < txtname.Length; index++) { if (bPreloadedEnitityBody[iStartIndex + index] != txtname[index]) { break; } i = 0; } if (i == 0) { iStartTxtname = iStartIndex + txtname.Length + 4;//加4是因为有两个\r\n break; } } while (iStartTxtname <= iEndIndex) { int i = -1; iStartIndex = Array.IndexOf(bPreloadedEnitityBody, b2[0], iStartTxtname + 1); if (iStartIndex < 0) { break; } for (int index = 1; index < b2.Length; index++) { if (bPreloadedEnitityBody[iStartIndex + index] != b2[index]) { break; } i = 0; } if (i == 0) { iEndTxtname = iStartIndex; break; } } filename = eContentEncode.GetString(bPreloadedEnitityBody, iStartTxtname, iEndTxtname - iStartTxtname); ufiFileInfo.StrFileName = filename; //开始写文件 ufiFileInfo.IFileStart = iDataStart3; //获取后缀名 ufiFileInfo.strExtensionName = GetExtensionName(bPreloadedEnitityBody, 0, bPreloadedEnitityBody.Length - 1); FileStream fs; DirectoryInfo diTempFileDir = new DirectoryInfo(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//")); if (!diTempFileDir.Exists) {//说明是对新文件的第一次读取,先创建临时文件夹和文件 Directory.CreateDirectory(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//")); } FileInfo fiFile = new FileInfo(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + filename + "." + ufiFileInfo.strExtensionName)); if (!fiFile.Exists) { fs = File.Create(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + filename + "." + ufiFileInfo.strExtensionName)); } else { fs = new FileStream(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + filename + "." + ufiFileInfo.strExtensionName), FileMode.Open, FileAccess.Write); } //或取文件结束分隔符 iEndStart = GetIndexOfByte(bPreloadedEnitityBody, bboundary, ufiFileInfo.IFileStart, bPreloadedEnitityBody.Length - 1, 0); //如果没有找到,说明文件还没有结束 if (iEndStart < 0) {//本次请求只有部分文件数据 temp = new byte[bboundary.Length]; Array.Copy(bPreloadedEnitityBody, bPreloadedEnitityBody.Length - bboundary.Length, temp, 0, bboundary.Length);//预留一部分数组防止分界标志位于两个数据块中 fs.Write(bPreloadedEnitityBody, ufiFileInfo.IFileStart, bPreloadedEnitityBody.Length - bboundary.Length - ufiFileInfo.IFileStart); bReadDataFinished = false; bGoOnGetFileFromThisByte = false;//因为在本次数组中只读取了部分文件数据,所以说明本次数组已经完全读取完毕。 } else {//本次请求包含完整的文件数据 if (GetIndexOfByte(bPreloadedEnitityBody, bendboundary, iEndStart, bPreloadedEnitityBody.Length - 1, 0) > 0)//这里可以提高下查询性能,可以直接从最后几个字符查起 {//说明请求数据已经全步读取完毕 bGoOnGetFileFromThisByte = false; } else { bGoOnGetFileFromThisByte = true; } } fs.Flush(); fs.Close(); fs.Dispose(); //保留一段临时数组(防止分割分隔符) if (bGoOnGetFileFromThisByte) { temp = new byte[bPreloadedEnitityBody.Length - iEndStart]; Array.Copy(bPreloadedEnitityBody, iEndStart, temp, 0, bPreloadedEnitityBody.Length - iEndStart); bPreloadedEnitityBody = UnionByte(temp, null); temp = null; } } else { int iEndStart = 0; bPreloadedEnitityBody = UnionByte(bPreloadedEnitityBody, temp); FileStream fs = new FileStream(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + filename + "." + ufiFileInfo.strExtensionName), FileMode.Append, FileAccess.Write); iEndStart = GetIndexOfByte(bPreloadedEnitityBody, bboundary, ufiFileInfo.ICurrentIndex, bPreloadedEnitityBody.Length - 1, 0); if (iEndStart < 0) {//文件数据没有结束 temp = new byte[bboundary.Length]; Array.Copy(bPreloadedEnitityBody, bPreloadedEnitityBody.Length - bboundary.Length, temp, 0, bboundary.Length);//预留一部分数组防止分界标志位于两个数据块中 fs.Write(bPreloadedEnitityBody, 0, bPreloadedEnitityBody.Length - bboundary.Length); bGoOnGetFileFromThisByte = false; } else { if (iEndStart > 0) { if (GetIndexOfByte(bPreloadedEnitityBody, bendboundary, iEndStart, bPreloadedEnitityBody.Length - 1, 0) > 0)//这里可以提高下查询性能,可以直接从最后几个字符查起 {//说明请求数据已经全部读取完毕 bGoOnGetFileFromThisByte = false; } else { bGoOnGetFileFromThisByte = true; } } bReadDataFinished = true; } fs.Flush(); fs.Close(); fs.Dispose(); if (bGoOnGetFileFromThisByte) { temp = new byte[bPreloadedEnitityBody.Length - iEndStart]; Array.Copy(bPreloadedEnitityBody, iEndStart, temp, 0, bPreloadedEnitityBody.Length - iEndStart); bPreloadedEnitityBody = UnionByte(temp, null); temp = null; } } byte[] bReadStepByte = new byte[iReadStepSize]; ufiFileInfo.dtStartFileRecv = DateTime.Now; ufiFileInfo.iReadedBytes = iRead; if (!request.IsEntireEntityBodyIsPreloaded()) { while (iLeave > iReadStepSize && request.IsClientConnected()) { iRead = request.ReadEntityBody(bReadStepByte, iReadStepSize);//之前不能去请求其它的数据 GetFile(bReadStepByte, ufiFileInfo); ufiFileInfo.iReadedBytes += iRead; iLeave -= iRead; } if (iLeave > 0 && request.IsClientConnected()) { iRead = request.ReadEntityBody(bReadStepByte, iLeave);//最后还剩一部分,因为小于n,所以写在循环外 byte[] bLastByte = new byte[iRead]; for (int i = 0; i < iRead; i++) { bLastByte[i] = bReadStepByte[i]; } GetFile(bLastByte, ufiFileInfo); ufiFileInfo.iReadedBytes += iRead; } } } #region 从数据块中获取文件内容 /// <summary> /// 从数据块中获取文件内容 /// </summary> /// <param name="bFileByte">数据块</param> private void GetFile(byte[] bFileByte, UploadFileInfo ufiFileInfo) { bool bGoOnGetFileFromThisByte = true;//当一个新文件读取结束时为true。用以读取多个上传文件 while (bGoOnGetFileFromThisByte) { try { if (bFileByte.Length < 1) return; if (bReadDataFinished) {//对一个新文件的第一次读取 if (temp != null) { bFileByte = UnionByte(bFileByte, temp); } #region 判断是否有文件数据头 int iDataStart = 0, iDataStart2 = 0, iDataStart3 = 0, iEndStart = 0; iDataStart = GetIndexOfByte(bFileByte, eContentEncode.GetBytes("filename="), 0, bFileByte.Length - 1, 9);//获取"filename="后的位置 if (iDataStart < 0) { temp = new byte[bendboundary.Length]; Array.Copy(bFileByte, bFileByte.Length - temp.Length, temp, 0, temp.Length);//预留一部分数组防止"filename="位于两个数据块中 return; } iDataStart2 = GetIndexOfByte(bFileByte, eContentEncode.GetBytes("\r\n"), iDataStart, bFileByte.Length - 1, 2);//获取\r\nContent-Type: text/plain这句话的起始坐标,这之后有两个换言之行符,所以下句偏移4 if (iDataStart2 < 0) { temp = new byte[bFileByte.Length - iDataStart + 9];//大小应该为数据块的结束位置-filename的起始位置+1,这样方便获取文件名 Array.Copy(bFileByte, bFileByte.Length - temp.Length, temp, 0, temp.Length);//预留一部分数组防止文件名位于两个数据块中 return; } ufiFileInfo.strExtensionName = GetExtensionName(bFileByte, 0, bFileByte.Length - 1); iDataStart3 = GetIndexOfByte(bFileByte, eContentEncode.GetBytes("\r\n"), iDataStart2, bFileByte.Length - 1, 4);//获取文件开始处的位置 if (iDataStart3 < 0) { temp = new byte[bFileByte.Length - iDataStart + 9];//大小应该为数据块的结束位置-filename的起始位置+1,这样方便获取文件名 Array.Copy(bFileByte, bFileByte.Length - temp.Length, temp, 0, temp.Length);//预留一部分数组防止文件名后的"Content-Type....\r\n"位于两个数据块中 return; } #endregion ufiFileInfo.IFileStart = iDataStart3; FileStream fs; try { DirectoryInfo diTempFileDir = new DirectoryInfo(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//")); if (!diTempFileDir.Exists) {//说明是对新文件的第一次读取,先创建临时文件夹和文件 Directory.CreateDirectory(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//")); } FileInfo fiFile = new FileInfo(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + ufiFileInfo.StrFileName + "." + ufiFileInfo.strExtensionName)); if (!fiFile.Exists) { fs = File.Create(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + ufiFileInfo.StrFileName + "." + ufiFileInfo.strExtensionName)); } else { fs = new FileStream(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + ufiFileInfo.StrFileName + "." + ufiFileInfo.strExtensionName), FileMode.Open, FileAccess.Write); } iEndStart = GetIndexOfByte(bFileByte, bboundary, ufiFileInfo.IFileStart, bFileByte.Length - 1, 0); if (iEndStart < 0) {//本次请求只有部分文件数据 temp = new byte[bboundary.Length]; Array.Copy(bFileByte, bFileByte.Length - bboundary.Length, temp, 0, bboundary.Length);//预留一部分数组防止分界标志位于两个数据块中 fs.Write(bFileByte, ufiFileInfo.IFileStart, bFileByte.Length - bboundary.Length - ufiFileInfo.IFileStart); bReadDataFinished = false; bGoOnGetFileFromThisByte = false;//因为在本次数组中只读取了部分文件数据,所以说明本次数组已经完全读取完毕。 } else {//本次请求包含完整的文件数据 if (GetIndexOfByte(bFileByte, bendboundary, iEndStart, bFileByte.Length - 1, 0) > 0)//这里可以提高下查询性能,可以直接从最后几个字符查起 {//说明请求数据已经全步读取完毕 // WriteHttpRequestWithoutFileData(bFileByte, iEndStart, bFileByte.Length - iEndStart, ref brequest); bGoOnGetFileFromThisByte = false; } else { bGoOnGetFileFromThisByte = true; } } fs.Flush(); fs.Close(); fs.Dispose(); } catch { ufiFileInfo.Status = UploadStatus.Error; return;//*****上传失败***** } if (bGoOnGetFileFromThisByte) { temp = new byte[bFileByte.Length - iEndStart]; Array.Copy(bFileByte, iEndStart, temp, 0, bFileByte.Length - iEndStart); bFileByte = UnionByte(temp, null); temp = null; } } else { int iEndStart = 0; bFileByte = UnionByte(bFileByte, temp); try { FileStream fs = new FileStream(HttpContext.Current.Server.MapPath("TempUpload/" + ufiFileInfo.strFileGuid + "//" + ufiFileInfo.StrFileName + "." + ufiFileInfo.strExtensionName), FileMode.Append, FileAccess.Write); iEndStart = GetIndexOfByte(bFileByte, bboundary, ufiFileInfo.ICurrentIndex, bFileByte.Length - 1, 0); if (iEndStart < 0) {//文件数据没有结束 temp = new byte[bboundary.Length]; Array.Copy(bFileByte, bFileByte.Length - bboundary.Length, temp, 0, bboundary.Length);//预留一部分数组防止分界标志位于两个数据块中 fs.Write(bFileByte, 0, bFileByte.Length - bboundary.Length); bGoOnGetFileFromThisByte = false; } else { if (iEndStart > 0) { if (GetIndexOfByte(bFileByte, bendboundary, iEndStart, bFileByte.Length - 1, 0) > 0)//这里可以提高下查询性能,可以直接从最后几个字符查起 {//说明请求数据已经全部读取完毕 bGoOnGetFileFromThisByte = false; } else { bGoOnGetFileFromThisByte = true; } } bReadDataFinished = true; } fs.Flush(); fs.Close(); fs.Dispose(); } catch { ufiFileInfo.Status = UploadStatus.Error; return;//*****上传失败***** } if (bGoOnGetFileFromThisByte) { temp = new byte[bFileByte.Length - iEndStart]; Array.Copy(bFileByte, iEndStart, temp, 0, bFileByte.Length - iEndStart); bFileByte = UnionByte(temp, null); temp = null; } } } catch { ufiFileInfo.Status = UploadStatus.Error; return;//*****上传失败***** } } } #endregion #region 获取上传标识ID private string GetUploadId(byte[] array, Encoding eEncode) { byte[] b1 = eEncode.GetBytes("Content-Disposition: form-data; name=\"EUploadID\""); int iStartIndex = GetIndexOfByte(array, b1, 0, array.Length - 1, 0); if (iStartIndex < 0) return string.Empty; else { iStartIndex = GetIndexOfByte(array, eEncode.GetBytes("\r\n\r\n"), iStartIndex, array.Length - 1, 4); if (iStartIndex < 0) return string.Empty; else { int iEndIndex = GetIndexOfByte(array, eEncode.GetBytes("\r\n"), iStartIndex, array.Length - 1, 0); if (iEndIndex < 0) return string.Empty; else return eEncode.GetString(array, iStartIndex, iEndIndex - iStartIndex); } } } #endregion #region 从数据块中读取文件扩展名 /// <summary> /// 从数据块中读取文件扩展名 /// </summary> /// <param name="array">数据块</param> /// <param name="istartindex">检索的起始位置</param> /// <param name="iendindex">检索的结束位置</param> /// <returns></returns> private string GetExtensionName(byte[] array, int istartindex, int iendindex) { byte[] b1 = eContentEncode.GetBytes("filename="); string strExtensionName; int iFileNameStartIndex = GetIndexOfByte(array, b1, istartindex, iendindex, b1.Length);//获取文件名的起始位置 if (iFileNameStartIndex < 0) {//注:可能该字段刚好处于两个数据块中 return string.Empty; } b1 = eContentEncode.GetBytes("\r\n");//"\r\n"占两个字节 int iFileNameEndIndex = GetIndexOfByte(array, b1, iFileNameStartIndex, iendindex, 0) - 2;//获取文件名结尾的位置 if (iFileNameEndIndex > iFileNameStartIndex) {//文件名格式是否正确直接在页面上处理,所以认为这里面的文件名合法 strExtensionName = eContentEncode.GetString(array, iFileNameStartIndex + 1, iFileNameEndIndex - iFileNameStartIndex);//获取文件全名,包括了路径 } else { return string.Empty; } return strExtensionName.Substring(strExtensionName.LastIndexOf(".") + 1); } #endregion #region 获取小数组在大数组中的位置 /// <summary> /// 获取小数组在大数组中的位置 /// </summary> /// <param name="b1">大数组</param> /// <param name="b2">小数组</param> /// <param name="iStartIndex">在大数组中检索的起始位置</param> /// <param name="iEndIndex">可在大数组中检索的最大的位置</param> /// <param name="iOffset">偏移量</param> /// <returns>检索到的位置和偏移量的和</returns> private int GetIndexOfByte(byte[] b1, byte[] b2, int iStartIndex, int iEndIndex, int iOffset) { int i = -1;//用来表示是否出错 if (iStartIndex < 0 || iEndIndex < 0 || iStartIndex > iEndIndex) return -1; if (b2.Length == 1) {//如果小数组的长度就是1那表明查询一次就可以找到,不需要while return Array.IndexOf(b1, b2[0], iStartIndex); } while (iStartIndex <= iEndIndex) {//"="的情况是在b1只有一个字节的时候发生 iStartIndex = Array.IndexOf(b1, b2[0], iStartIndex);//从b1中的iStartIndex位置处开始检索b2[0],没检索到则返回-1; if (iStartIndex < 0) { return -1; } for (int index = 1; index < b2.Length; index++) {//对剩余的字节进行逐个匹配 if (iStartIndex + index > iEndIndex) {//如果索引的起点+预检索字符的长度>大数组的最大下标,则没有找到。 return -1; } if (b1[iStartIndex + index] != b2[index]) { i = -1; iStartIndex++; break; } } if (i >= 0) {//如果i>=0则说明找到完全匹配的 i = iStartIndex; i += iOffset; break; } else { i = 0; } } return i; } #endregion #region 获取分隔符的字符数组 /// <summary> /// 获取分隔符的字符数组 /// </summary> /// <param name="ContentType">请求类型</param> /// <returns>分隔符字节数组</returns> private byte[] GetMultipartBoundary(string ContentType) { int nPos = ContentType.IndexOf("boundary="); string sTemp = ContentType.Substring(nPos + 9); string sBoundary = sTemp = "--" + sTemp; return Encoding.ASCII.GetBytes(("\r\n" + sTemp).ToCharArray()); } /// <summary> /// 获取结束分隔符的字符数组 /// </summary> /// <param name="ContentType">请求类型</param> /// <returns>分隔符字节数组</returns> private byte[] GetEndBoundary(string ContentType) { int nPos = ContentType.IndexOf("boundary="); string sTemp = ContentType.Substring(nPos + 9); string sBoundary = sTemp = "--" + sTemp + "--"; return Encoding.ASCII.GetBytes(("\r\n" + sTemp).ToCharArray()); } #endregion #region 拼合两个数组 private byte[] UnionByte(byte[] bnewbyte, byte[] boldbyte) { int iLen = 0; if (bnewbyte != null) {//要添加到原数组中的字节如果不为空 if (boldbyte != null) { iLen = boldbyte.Length; } byte[] unionbyte = new byte[bnewbyte.Length + iLen]; if (boldbyte != null) { boldbyte.CopyTo(unionbyte, 0); } bnewbyte.CopyTo(unionbyte, iLen); return unionbyte; } else { return boldbyte; } } #endregion public void Dispose() { } public upLoad() { // //TODO: 在此处添加构造函数逻辑 // } }
三,UploadFileInfo类是为了储存进度数据:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; /// <summary> ///UploadFileInfo 的摘要说明 /// </summary> public class UploadFileInfo { /// <summary> /// 已经上传的字节数 /// </summary> public int iReadedBytes = 0; /// <summary> /// 需传的字节总数 /// </summary> public int iTotalBytes = 0; public double iTotalSeconds = 0; /// <summary> /// 文件开始接收的时间 /// </summary> public DateTime dtStartFileRecv; private string strFullName; /// <summary> /// 文件名:包含文件的完整路径 /// </summary> public string StrFullName { get { return strFullName; } set { strFullName = value; } } private string strFileName; /// <summary> /// 文件名 /// </summary> public string StrFileName { get { return strFileName; } set { strFileName = value; } } private int iFileStart; /// <summary> /// 文件数据部分的起始索引 /// </summary> public int IFileStart { get { return iFileStart; } set { iFileStart = value; } } /// <summary> /// 文件扩展名 /// </summary> public string strExtensionName; private int iCurrentIndex; public int ICurrentIndex { get { return iCurrentIndex; } set { iCurrentIndex = value; } } /// <summary> /// 返回上传速度,单位K/S /// </summary> public double fSpeed { get { if (iReadedBytes <= 0) { return 0; } TimeSpan ts = DateTime.Now - dtStartFileRecv; if (ts.TotalSeconds > 0) { this.iTotalSeconds = ts.TotalSeconds; return double.Parse((iReadedBytes / 1024 / ts.TotalSeconds).ToString("0.0")); } else { return 0; } } } /// <summary> /// 读取文件上传的进度 /// </summary> public int iPercent { get { if (iTotalBytes > 0) return Convert.ToInt32(Math.Floor((iReadedBytes / (double)iTotalBytes) * 100)); else return 0; } } private string str_FileGuid = string.Empty; /// <summary> /// 文件的唯一标识 /// </summary> public string strFileGuid { get { return str_FileGuid; } set { str_FileGuid = value; } } public bool bHasErrorInfo = false; /// <summary> /// 上传的状态 /// </summary> public UploadStatus Status = UploadStatus.Initializing; private string str_TempDir; /// <summary> /// 文件的临时路径 /// </summary> public string strTempDir { get { return str_TempDir; } set { str_TempDir = value; } } public UploadFileInfo() { // // TODO: 在此处添加构造函数逻辑 // } public UploadFileInfo(string sFileName) { strFileName = sFileName; } public void SaveAs(string strSavePath) { if (!strSavePath.EndsWith("\\")) { strSavePath = strSavePath + "\\"; } DirectoryInfo di = new DirectoryInfo(strTempDir); if (di.Exists) { try { Directory.CreateDirectory(strSavePath); foreach (FileInfo fi in di.GetFiles()) { fi.MoveTo(strSavePath + fi.Name); } Status = UploadStatus.Finish; } catch { Status = UploadStatus.Error; } } else { Status = UploadStatus.Error; } } } /// <summary> /// 上传的状态 /// </summary> public enum UploadStatus { /// <summary> /// 上传过程中出现错误 /// </summary> Error, /// <summary> /// 正在初始化 /// </summary> Initializing, /// <summary> /// 正在上传 /// </summary> Uploading, /// <summary> /// 文件已经成功上传 /// </summary> Finish, /// <summary> /// 上传过程被用户取消 /// </summary> CanceledByUser }
四,EXTJS就是它需要用到的一些文件。版本是extjs4.2
五,TempUpload文件上传文件夹。
六,Progress.aspx与Progress.cs
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Progress.aspx.cs" Inherits="Progress" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script type="text/javascript"> function myRefresh(url) { setTimeout(location.replace(url), 1000); } </script> </head> <body> <form id="form1" runat="server"> <div> </div> </form> </body> </html>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Text; public partial class Progress : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { UploadFileInfo ufi = null; ufi = (UploadFileInfo)HttpContext.Current.Cache[Request["UploadID"]]; string stratevent = Request.QueryString["event"]; if (!IsPostBack) { if (stratevent == null) { if (ufi == null) { return; } else { StringBuilder script = new StringBuilder(); script.Append("<script>myRefresh('Progress.aspx?UploadID=" + ufi.strFileGuid + "&event=start');</script>"); ClientScript.RegisterClientScriptBlock(this.GetType(), "js", script.ToString()); } } } if (stratevent != null) { if (stratevent.ToLower() == "start" && ufi != null) { Response.Write(ufi.iPercent); Response.Flush(); Response.Close(); if (ufi.iPercent == 100) { ufi.iReadedBytes = 0; } } } } }
七,upfileload.aspx与upfileload.cs
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="upfileload.aspx.cs" Inherits="upfileload" %> <%if (Request.Params["upload"] != "true") { %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title> <link href="extjs/resources/css/ext-all.css" rel="stylesheet" type="text/css" /> <script src="extjs/ext-all-debug.js" type="text/javascript"></script> <script src="extjs/locale/ext-lang-zh_CN.js" type="text/javascript"></script> <script type="text/javascript"> Ext.onReady(function () { Ext.QuickTips.init(); // var msg = function (title, msg) { // Ext.Msg.show({ // title: title, // msg: msg, // minWidth: 200, // model: true // }); // } var fp = Ext.create('Ext.form.Panel', { renderTo: document.getElementById("form1"), width: 500, frame: true, title: '图片上传', autoHeight: true, bodyStyle: 'padding: 10px 10px 0 10px;', labelWidth: 50, defaults: { anchor: '95%', allowBlank: false, msgTarget: 'side' }, items: [{ xtype: 'hiddenfield', name: 'EUploadID', id: 'EUploadID', value: document.getElementById("UploadID").value }, { xtype: 'textfield', name: 'txtname', id: 'txtname', fieldLabel: 'Name' }, { xtype: 'filefield', id: 'form-file', emptyText: 'Select an image', fieldLabel: 'Photo', name: 'photo-path', buttonText: '浏览' }, { xtype: 'progressbar', id: 'pgb' }], buttons: [{ text: 'Save', handler: function () { if (fp.getForm().isValid()) { fp.getForm().submit({ type: 'POST', url: 'upfileload.aspx?action=upload&upload=true', success: function (fp, o) { } }); ; var f = function (v) { var i = v / 100; Ext.getCmp("pgb").updateProgress(i, '进度:' + v + '/100'); if (v == 100) { Ext.getCmp("pgb").reset(); //复位进度条 Ext.getCmp("pgb").updateText('完成'); } } var xmlhttp; function loadXMLDoc(url) { xmlhttp = null; if (window.XMLHttpRequest) {// code for IE7, Firefox, Opera, etc. xmlhttp = new XMLHttpRequest(); } else if (window.ActiveXObject) {// code for IE6, IE5 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } if (xmlhttp != null) { xmlhttp.open("GET", url, true); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { var temp = xmlhttp.responseText; f(temp); if (temp != 100) { loadXMLDoc("Progress.aspx?event=start&UploadID=" + document.getElementById("UploadID").value); } temp = 0; } } xmlhttp.send(null); } else { alert("Your browser does not support XMLHTTP."); } } loadXMLDoc("Progress.aspx?event=start&UploadID=" + document.getElementById("UploadID").value); } } }, { text: 'Reset', handler: function () { fp.getForm().reset(); } }] }); }); </script> </head> <body> <form id="form1" runat="server"> </form> <div id="progress" style="display: none" runat="server"> </div> </body> </html> <%} %>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class upfileload : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { UploadFileInfo ufi = new UploadFileInfo(); ufi.strFileGuid = Guid.NewGuid().ToString();//还是换成guid比较好,因为有可能会产生同一时刻上传的动作 //ScriptManager.RegisterHiddenField(); ClientScript.RegisterHiddenField("UploadID", ufi.strFileGuid); HttpContext.Current.Cache.Add(ufi.strFileGuid, ufi, null, DateTime.Now.AddDays(10), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null); progress.InnerHtml = "<iframe src='Progress.aspx?UploadID=" + ufi.strFileGuid + "' width='100%' scrolling=no frameborder='0'></iframe>"; } } }
八,web.config
<?xml version="1.0"?> <!-- 有关如何配置 ASP.NET 应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=169433 --> <configuration> <system.web> <httpModules> <add name="MyUpLoad" type="upLoad"/> </httpModules> <httpRuntime maxRequestLength="8192" executionTimeout="300000"/> <compilation debug="true" targetFramework="4.0"/> </system.web> </configuration>