Вопрос по asp.net, c# – ASP.NET C # OutofMemoryException при загрузке большого файла

4

У меня есть следующий обработчик загрузки файла:

public class FileUploader : IHttpHandler
{
 public void ProcessRequest(HttpContext context)
 {
    HttpRequest request = context.Request;

    context.Response.ContentType = "text/html";
    context.Response.ContentEncoding = System.Text.Encoding.UTF8;
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    var tempPath = request.PhysicalApplicationPath + "\\Files\\TempFiles\\";        
    byte[] buffer = new byte[request.ContentLength];
    using (BinaryReader br = new BinaryReader(request.InputStream))
    {
        br.Read(buffer, 0, buffer.Length);
    }
    var tempName = WriteTempFile(buffer, tempPath);
    context.Response.Write("{\"success\":true}");
    context.Response.End();
 }

 public bool IsReusable
 {
    get { return true; }
 }

 private string WriteTempFile(byte[] buffer, string tempPath)
 {
    var fileName = GetUniqueFileName(tempPath);
    File.WriteAllBytes(tempPath + fileName, buffer);
    return fileName;
 }
 private string GetUniqueFileName(string tempPath)
 {
    var guid = Guid.NewGuid().ToString().ToUpper();
    while (File.Exists(tempPath + guid))
    {
        guid = Guid.NewGuid().ToString().ToUpper();
    }
    return guid;
 }
}

Когда я загружаю большие файлы, это вызывает исключение OutOfMemoryException. Может ли кто-нибудь сказать, как правильно загружать большие файлы с помощью такого обработчика?

99% времени, используяBinaryReader/Writer это очень неправильный выбор. leppie
Есть два ответа, они делают ту же работу? Если нет, какой из них лучше другого и почему? Babu James

Ваш Ответ

2   ответа
4

Вы получаете OutOfMemoryException, потому что загружаете загруженный файл в память. Избегайте этого, записав свой поток непосредственно в файл.

public void ProcessRequest(HttpContext context)
 {
    const int BufferSize = 4096;    

    HttpRequest request = context.Request;

    context.Response.ContentType = "text/html";
    context.Response.ContentEncoding = System.Text.Encoding.UTF8;
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    var tempFilePath = Path.GetTempFileName();        

    using (Stream fs = File.OpenWrite(tempFilePath));
    {
        byte[] buffer = new byte[BufferSize];
        int read = -1;
        while(read = request.InputStream.Read(buffer, 0, buffer.Length) > 0)
        {            
             fs.Write(buffer, 0, buffer.Length);             
        }
    }

    context.Response.Write("{\"success\":true}");
    context.Response.End();
 }

редактировать: удаленный двоичный

7

Нет необходимости загружать файл в память, чтобы записать его куда-нибудь. Вы должны использоватьsmall буфер (возможно, 8 Кб) и циклический перебор потоков. Или, с 4.0,CopyTo метод. Например:

using(var newFile = File.Create(tempPath)) {
    request.InputStream.CopyTo(newFile);
}

(который делает маленький буфер / цикл для вас, используя буфер 4 КБ по умолчанию, или позволяя пропускать пользовательский размер буфера через перегрузку)

да это оно! забудь мой ответ :)

Похожие вопросы