Converting HttpPostedFileBase to byte []: Exception_WasThrown

9

Follow the code below:

Controller (with post action):

var file = Request.Files[0];
var bytes = ConvertTo.Bytes(file);

ConvertTo Class:

public static byte[] Bytes(HttpPostedFileBase result)
{
    var length = result.InputStream.Length; //Length: 103050706
    MemoryStream target = new MemoryStream();
    result.InputStream.CopyTo(target); // gera problema nessa linha aqui
    byte[] data = target.ToArray(); 
    return data;
}

The file size is: 98.2 MB (103,050,706 bytes), file size 60 MB works perfectly.

In line: result.InputStream.CopyTo(target); I get error:

  

System.OutOfMemoryException: 'Exception_WasThrown'

Small file works fine, only big file does this problem.

Any solution for large file?

UPDATE:

Follow the code below:

public static byte[] ConverToBytes(HttpPostedFileBase file)
{
    var length = file.InputStream.Length; //Length: 103050706
    byte[] fileData = null;
    using (var binaryReader = new BinaryReader(file.InputStream))
    {
        fileData = binaryReader.ReadBytes(file.ContentLength);
    }
    return fileData;
}

Code above works using BinaryReader . Why does MemoryStream not work?

    
asked by anonymous 12.10.2017 / 17:50

4 answers

5

Hello, I do not know how MemoryStream works from the inside, but I did a profiler on your method and the method I did that I think would be 'light'.

By exception the problem is lack of memory so I thought of a code that could solve the problem with its memory limitation.

I took the liberty of putting the parameter as Stream and not HttpPostedFile to facilitate the test.

For the test I used the RapidMiner installer which is about 171MB.

Below is the result with your code, I do not know why you used so much memory:

public static byte[] Bytes2(Stream result)
        {
            var length = result.Length; //Length: 103050706
            MemoryStream target = new MemoryStream();
            result.CopyTo(target); // gera problema nessa linha aqui
            byte[] data = target.ToArray();
            return data;
        }

BelowIdidusingacodewithoutperformingtheinstanceofMemoryStream,seethedifference:

publicstaticbyte[]Bytes(Streamresult){longlength=result.Length;byte[]data=newbyte[length];result.Read(data,0,(int)length);//atéint.maxestáokreturndata;}

Try using this second code and tell me if the problem has been resolved.

    
23.10.2017 / 18:57
4

The MemoryStream creates an internal buffer with a default value, which only grows according to the demand of the past data.

If the data you pass exceeds the size that was pre-allocated, a new buffer with double the size is created, which receives all the contents of the old buffer.

For example: If you allocate 128MB of memory and your file consumes more than this, MemoryStream will attempt to allocate 256mb, and so on, doubling the size, making the resource extremely costly.

This error may have to do with the application process settings too, if it is in 32bit. Try to build in your application with the x64 setting.

I used this response from SOen as a reference.

    
23.10.2017 / 19:09
0
public static byte[] Bytes(HttpPostedFileBase result)
{
    byte[] data;
    using (Stream inputStream = result.InputStream)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            inputStream.CopyTo(ms);
            data = ms.ToArray();
        }
    }
    return data;
}

You instantiated MemoryStream twice in MemoryStream memoryStream = inputStream as MemoryStream; and inputStream.CopyTo(memoryStream); . There were lines that did not make sense in the code.

Above, MemoryStream is created in a new instance. The bytes of inputStream are copied to ms , and thus returned.

    
13.10.2017 / 02:40
-3

A good way out is to resize this image.

public ActionResult Thumbnail(string filename)
{
var img = new WebImage(filename).Resize(291, 285, false, true);
return new ImageResult(new MemoryStream(img.GetBytes()), "binary/octet-stream");
}

WebImage class documentation on MSDN.

    
23.10.2017 / 21:44