文件上傳之--內存溢出(System.OutOfMemoryException)

兩週前就想把這點經驗記錄下來了,因爲拖延症上身,直到剛纔忽然想起這件未完成的任務,今天是1024,在這個特別的日子裏,祝全部程序猿兄弟姐妹們節日快樂!web

上傳功能一直很正常,直到上傳了個500多兆的文件,報錯提示:數組

「System.OutOfMemoryException」類型的異常在 mscorlib.dll 中發生,但未在用戶代碼中進行處理瀏覽器

對於內部用途和新的託管對象,確保要有足夠的內存可供分配。
若是要建立數組,請確保大小正確。dom

因爲調用的webservice中的文件上傳方法參數爲二進制格式,須要把文件流轉換爲byte格式,因此直接寫了byte[] byte = new byte[stream.Length],結果那個大文件就是在這句卡住了,一開始也很蒙圈,已經在配置文件中修改了最大請求的長度爲什麼還會有問題,調試代碼發現new byte[]的時候括號內要求參數是一個8位的整數,那個500多兆的文件轉爲字節後是個9位數,致使byte類型超出索引,因而想到每次實例化一個固定長度的byte,讓文件循環寫入,寫滿一個byte就放入數組,而後在服務端在解析這個數組便可,這樣就不會存在內存溢出的問題了,下面是示例代碼,僅供參考,若要帶走,歡迎轉發。post

腳本部分在上一篇中有代碼展現,這裏只展現後臺和服務端代碼了。spa

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服務端部分:code

  /// <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;
    }

 

但願本文可以幫助遇到一樣問題的同窗們,若有不妥之處,歡迎指正。對象

相關文章
相關標籤/搜索