文件上传之--内存溢出(System.OutOfMemoryException)

时间:2024-01-17 17:54:50

两周前就想把这点经验记录下来了,由于拖延症上身,直到刚才突然想起这件未完成的任务,今天是1024,在这个特别的日子里,祝所有程序猿兄弟姐妹们节日快乐!

上传功能一直很正常,直到上传了个500多兆的文件,报错提示:

“System.OutOfMemoryException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理

对于内部用途和新的托管对象,确保要有足够的内存可供分配。
如果要创建数组,请确保大小正确。

由于调用的webservice中的文件上传方法参数为二进制格式,需要把文件流转换为byte格式,所以直接写了byte[] byte = new byte[stream.Length],结果那个大文件就是在这句卡住了,一开始也很蒙圈,已经在配置文件中修改了最大请求的长度为何还会有问题,调试代码发现new byte[]的时候括号内要求参数是一个8位的整数,那个500多兆的文件转为字节后是个9位数,导致byte类型超出索引,于是想到每次实例化一个固定长度的byte,让文件循环写入,写满一个byte就放入数组,然后在服务端在解析这个数组即可,这样就不会存在内存溢出的问题了,下面是示例代码,仅供参考,若要带走,欢迎转发。

脚本部分在上一篇中有代码展示,这里只展示后台和服务端代码了。

1.一般处理程序部分:

public void FileUpload(HttpContext context)
{
WebService ws = new WebService();
ws.Timeout = ; //单位毫秒,1小时 HttpFileCollection files = context.Request.Files;
if (files.Count > )
{
/*获取真实文件名,files[0].FileName这种方法在IE浏览器中上传会带有F://路径*/
string filename = System.IO.Path.GetFileName(files[].FileName);
HttpPostedFile file = files[];
Stream fs = file.InputStream; /*定义object数组,用来存放byte数据*/
object[] obj = new object[] { };
List<object> list = new List<object>();
int offcount = ; /* size:1M,unit:byte */
int LimitSize = ;/*限制大小150M,unit:byte*/
if (fs.Length > LimitSize)
{
context.Response.Write("OutOfSize");
context.Response.End();
return;
}
int filelen = (int)fs.Length;
if (filelen > offcount)
{
long offset = ;
byte[] postArray = new byte[offcount];
int temponum = filelen / offcount;
/*整数部分*/
for (int i = ; i <= temponum; i++)
{
long lkl = filelen;
postArray = new byte[offcount];
fs.Seek(offset, SeekOrigin.Begin);
fs.Read(postArray, , offcount);
list.Add(postArray);
offset += offcount;
}
/*剩余部分*/
if (temponum * offcount < filelen)
{
offcount = filelen - temponum * offcount;
byte[] lpostArray = new byte[offcount];
fs.Seek(offset, SeekOrigin.Begin);
fs.Read(lpostArray, , offcount);
list.Add(lpostArray);
}
}
else
{
byte[] postArray = new byte[file.ContentLength];
fs.Read(postArray, , file.ContentLength);
list.Add(postArray);
}
/*list集合转为object数组*/
obj = list.ToArray();
fs.Flush();
fs.Close();
/*计算文件大小,文件大于1M,单位用M,其他用KB*/
string filesize = string.Empty;
if (filelen > )
{ filesize = Math.Ceiling((double)filelen / (double) / (double)) + "M"; }
else
{ filesize = Math.Ceiling((double)filelen / (double)) + "KB"; } /*为防止流长度溢出byte,固定byte大小放入object数组*/
string result = ws.objUploadFile(obj, "FileFolder", filename);
}
}

2.webservice服务端部分:

  /// <summary>
/// 上传文件
/// </summary>
/// <param name="obj">分割的byte[]数组</param>
/// <param name="path">文件存放文件夹</param>
/// <param name="fileName">文件名字</param>
/// <returns>文件的路径</returns>
[WebMethod(Description = "上传文件,返回路径")]
public string objUploadFile(object[] obj, string path, string fileName)
{
string ReturnPath = string.Empty;
FileStream wf = null;
byte[] fs;
try
{
string _FileName = string.Empty;
string FilePath = "uploadfiles\\document\\" + path;
FilePath = Server.MapPath(FilePath);
if (!Directory.Exists(FilePath))
{
Directory.CreateDirectory(FilePath);
} System.Random rnd = new System.Random();
string tmp = rnd.Next().ToString();
_FileName = "File_" + tmp + "_" + fileName; //文件名加随机数字
wf = new FileStream(FilePath + "\\" + _FileName, FileMode.Append, FileAccess.Write);
if (obj.Length > )
{
for (int i = ; i < obj.Length; i++)
{
fs = (byte[])obj[i];
wf.Write(fs, , fs.Length);
}
}
wf.Close();
wf = null;
ReturnPath = "\\uploadfiles\\document\\" + path + "\\" + _FileName;
}
catch
{
ReturnPath = string.Empty;
}
finally
{
}
return ReturnPath;
}

希望本文能够帮助遇到同样问题的同学们,如有不妥之处,欢迎指正。