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


    两周前就想把这点经验记录下来了,由于拖延症上身,直到刚才突然想起这件未完成的任务,今天是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 = 3600000; //单位毫秒,1小时
    
            HttpFileCollection files = context.Request.Files;
            if (files.Count > 0)
            {
                /*获取真实文件名,files[0].FileName这种方法在IE浏览器中上传会带有F://路径*/
                string filename = System.IO.Path.GetFileName(files[0].FileName);
                HttpPostedFile file = files[0];
                Stream fs = file.InputStream;
    
                /*定义object数组,用来存放byte数据*/
                object[] obj = new object[] { };
                List<object> list = new List<object>();
                int offcount = 1048576; /* size:1M,unit:byte */
                int LimitSize = 157286400;/*限制大小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 = 0;
                    byte[] postArray = new byte[offcount];
                    int temponum = filelen / offcount;
                    /*整数部分*/
                    for (int i = 1; i <= temponum; i++)
                    {
                        long lkl = filelen;
                        postArray = new byte[offcount];
                        fs.Seek(offset, SeekOrigin.Begin);
                        fs.Read(postArray, 0, 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, 0, offcount);
                        list.Add(lpostArray);
                    }
                }
                else
                {
                    byte[] postArray = new byte[file.ContentLength];
                    fs.Read(postArray, 0, file.ContentLength);
                    list.Add(postArray);
                }
                /*list集合转为object数组*/
                obj = list.ToArray();
                fs.Flush();
                fs.Close();
                /*计算文件大小,文件大于1M,单位用M,其他用KB*/
                string filesize = string.Empty;
                if (filelen > 1048576)
                { filesize = Math.Ceiling((double)filelen / (double)1024 / (double)1024) + "M"; }
                else
                { filesize = Math.Ceiling((double)filelen / (double)1024) + "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(999999999).ToString();
                _FileName = "File_" + tmp + "_" + fileName; //文件名加随机数字
                wf = new FileStream(FilePath + "\" + _FileName, FileMode.Append, FileAccess.Write);
                if (obj.Length > 0)
                {
                    for (int i = 0; i < obj.Length; i++)
                    {
                        fs = (byte[])obj[i];
                        wf.Write(fs, 0, fs.Length);
                    }
                }
                wf.Close();
                wf = null;
                ReturnPath = "\uploadfiles\document\" + path + "\" + _FileName;
            }
            catch
            {
                ReturnPath = string.Empty;
            }
            finally
            {
            }
            return ReturnPath;
        }

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

  • 相关阅读:
    Gorm(表的操作以及索引的操作)
    推荐几个查看 Go 汇编源码的工具使用技巧
    使用 Go 剖析Linux容器实现原理
    Kubelet failed to "CreatePodSandbox" for coredns; failed to set bridge addr: could not add ip addr to "cni0": permission denied
    antdesignmobile学习框架
    infra容器和用户容器的关系
    go bufio缓存原理
    详解 gRPC 客户端长连接机制实现
    SpringBoot进阶教程(七十四)整合ELK
    hive通过nginx实现HA高可用
  • 原文地址:https://www.cnblogs.com/Jackie-sky/p/5995038.html
Copyright © 2020-2023  润新知