1

So i have been going at this for a few days and Im running into an issue. Im trying to make an ajax call that sends a byte[] to the controller in c#.

var data = { FtpUpload: self.Upload(), Attachment: self.Attachment() };
Base.ServiceCall("/Home/Upload", "post", data, true, function  (response) {...}

self.Attachment() contains a property for the 'byte[]'. Im using this to read the byte array from the file which works as planned.

self.OnImageUpload = function (vm, evt) {
  var file = evt.target.files[0];
  var reader = new FileReader();

  reader.onload = function () {
    var attachment = {
      ...
      Attachment: reader.result.split(',')[1]
    };
    self.Attachment(attachment);
  }

  reader.readAsDataURL(file);
};

When i do this with a 17mb file it works ok but when i do this with a 109mb file it throws a 500 error that says this.

[OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.]
   System.Web.Util.HttpEncoder.UrlDecode(Byte[] bytes, Int32 offset, Int32 count, Encoding encoding) +76
   System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding) +164
   System.Web.HttpRequest.FillInFormCollection() +77

[HttpException (0x80004005): The URL-encoded form data is not valid.]
   System.Web.HttpRequest.FillInFormCollection() +130
   System.Web.HttpRequest.EnsureForm() +69
   System.Web.HttpRequest.get_Form() +13
   System.Web.HttpRequestWrapper.get_Form() +14

I have added the proper settings to my web.config to allow for larger files like so.

<system.web>  
  <httpRuntime targetFramework="4.6" maxRequestLength="2147483647" executionTimeout="1600" requestLengthDiskThreshold="2147483647" />
</system.web>

<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="2147483647" />
    </requestFiltering>
  </security>
</system.webServer>

Im not sure what else to do.

NormTheThird
  • 176
  • 15
  • Since You get an out of memory exception I suspect that it's not your config the problem. Can you post the Web Site method receiving the data? I suspect the problem is there. Because you get an error 500 it mean it occurred on the server so it not you JavaScript that throw this exception. – Lorien Apr 11 '17 at 21:00
  • You should consider using `reader.readAsArrayBuffer()` if you want a byte array. `readAsDataURL` will base64-encode your file, which can increase the size of the data considerably. – Heretic Monkey Apr 11 '17 at 21:51
  • "You should consider using reader.readAsArrayBuffer() if you want a byte array." I tried this but the byte array comes through on the backend as null. Im trying to pass the array buffer to a byte[]. Do i need to convert it to anything first? – NormTheThird Apr 11 '17 at 22:12

1 Answers1

0

Based on the stack trace your call is failing inside HttpEncoder.UrlDecode which is only possible if you are sending your image as application/x-www-form-urlencoded which may or may not be the best option when you are dealing with heavy binary data.

Regardless of the content type you choose to use you would have to re-implement your post action using HttpPostedFileBase parameter which provides you with the InputStream.Read method instead of expecting the byte[] from the request form, see below.

[HttpPost]
public JsonResult Upload(HttpPostedFileBase uploadedFile)
...
byte[] fileByteArray = new byte[uploadedFile.ContentLength];
uploadedFile.InputStream.Read(fileByteArray, 0, uploadedFile.ContentLength);
...

You could see in the example that the action parameter has to be HttpPostedFileBase in order to stream file instead of sending/receiving as a whole array of binary data.

Have a look at the following project below https://www.codeproject.com/Articles/1021004/Upload-File-Using-Ajax-And-HTML-in-MVC

Eugene Komisarenko
  • 1,533
  • 11
  • 25
  • I tried this and it still did not work. Thanks anyways. – NormTheThird Apr 11 '17 at 22:18
  • You should be getting another exception stack trace in this case. Can you please check? – Eugene Komisarenko Apr 11 '17 at 22:21
  • [OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.] System.Web.Util.HttpEncoder.UrlDecode(Byte[] bytes, Int32 offset, Int32 count, Encoding encoding) +76 System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding) +164 System.Web.HttpRequest.FillInFormCollection() +77 – NormTheThird Apr 11 '17 at 22:35
  • [HttpException (0x80004005): The URL-encoded form data is not valid.] System.Web.HttpRequest.FillInFormCollection() +130 System.Web.HttpRequest.EnsureForm() +69 System.Web.HttpRequest.get_Form() +13 System.Web.HttpRequestWrapper.get_Form() +14 System.Web.Mvc.HttpRequestExtensions.GetHttpMethodOverride(HttpRequestBase request) +121 System.Web.Mvc.AcceptVerbsAttribute.IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) +37 – NormTheThird Apr 11 '17 at 22:35
  • Hmm strange, stack trace is the same, which means you are still posting with 'application/x-www-form-urlencoded'. You may want to check the request headers in Fiddler to double check. – Eugene Komisarenko Apr 11 '17 at 22:39
  • I change my ajax call to use this and now it goes through but all objects are empty. – NormTheThird Apr 11 '17 at 22:50
  • That's a different story then )). Check this answer http://stackoverflow.com/a/14049848/920557 and you may want to lookup some examples of how to implement post action for this scenario. – Eugene Komisarenko Apr 11 '17 at 23:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/141569/discussion-between-eugene-komisarenko-and-normthethird). – Eugene Komisarenko Apr 12 '17 at 15:06