3

I have the following model :

public class FileModel
{
  public byte[] FileData{get;set;}
  public string FileName {get;set;}
}

I have coded a private Web API service which my Web application consumes. When the user uploads files, I convert those files to a byte array, and send a List<FileModel> to my Web API from C# code (not from an HTML page, since my Web API is private from my website), which saves my file and return results.

Web API method:

[HttpPost]
public UploadFiles(List<FileModel> files)
{
// Do work
}

The above code breaks if I upload many large-sized files - the code failed to serialize the large files' FileModels since they exceed the max serializing length.

How do I fix this issue? Is there any other way to upload files to Web API without exposing it to the users?

alex
  • 6,818
  • 9
  • 52
  • 103
Vignesh Pandi
  • 349
  • 1
  • 4
  • 15
  • Possible duplicate of [how to upload a large file with ASP.NET MVC4 Web Api with progressbar](https://stackoverflow.com/questions/15506648/how-to-upload-a-large-file-with-asp-net-mvc4-web-api-with-progressbar) – Liam Oct 12 '17 at 12:23
  • Use chunk byte approach to upload asynchronously. https://stackoverflow.com/questions/583970/need-loop-to-copy-chunks-from-byte-array – Nikhil K S Oct 12 '17 at 12:31
  • @NikhilKS I don't want to make multiple web api calls. – Vignesh Pandi Oct 12 '17 at 12:42

2 Answers2

2

Here is some solution for that situation.

Your controller action will not accept any parameters as shown on code snippet.

public async Task<HttpResponseMessage> PostByteArrayAsync()
{
       string root = HttpContext.Current.Server.MapPath("~/folder");
       var provider = new MultipartFormDataStreamProvider(root);
       await Request.Content.ReadAsMultipartAsync(provider);
       foreach (var file in provider.FileData)
       {
             var buffer = File.ReadAllBytes(file.LocalFileName);
             // store to db and other stuff
       }
       return Ok();
}

And the code above for front end sample.

UploadData(event) {
        this.setState({ loading: true });
        event.preventDefault();
        let data = new FormData();
        let fileData = document.querySelector('input[type="file"]').files[0];
        data.append("data", fileData);
        let that = this;
        fetch("api/upload", {
            method: "POST",
            "Content-Type": "multipart/form-data",
            "Accept": "application/json",
            body: data
        }).then(function (res) {
            if (res.ok) {
                call('api', 'GET').then(response => { response.error ? response.message : that.props.change(response); that.setState({ loading: false }) });
            }
            else {
                that.setState({ loading: false });
                that.failedMsg();
            }
        })
    }
narekye
  • 114
  • 3
  • hi thanks for the response but I'm not trying to POST file to my Web API directly.I'm posting file to my MVC action controller and making my controller action POST file to my Web API.I don't want my Web API url exposed since its private (i.e. specific to my website) – Vignesh Pandi Oct 14 '17 at 18:58
1

Add this in your web.config file.

<configuration>
   <system.web>
      <httpRuntime maxRequestLength ="1999999"/>
</system.web>
</configuration>

And also increase your content length in MVC config file.

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

maxRequestLength value is in kilobytes.

maxAllowedContentLength value is in bytes.

You can change above size according to your requirements.

Amit Kumar
  • 5,888
  • 11
  • 47
  • 85