0

I have a Silverlight application that uses Web API to upload a document that is stored in a Database as a Filestream. Currently it's done by a POST with a Content-Type: application/json. The object containing a byte array of the File along with some metadata about the file is serialized to JSON and posted to the Web API. Web API then saves the byte array as a Filestream to the Database.

Following is a sample of the current request:

{"FileContent":"JVBERi0xLjUNJeLjz9MNCjEwIDAgb2JqDTw8L0xpbmVhcml6ZWQgMS9MIDI3MTg2L08gMTIvRSAyMjYyNi9OIDEvVCAyNjg4NC9IIFsgNDg5IDE2OF0+Pg1lbmRvYmoNICAgICAgICAgICAgICAgICAgDQoyNyAwIG9iag08PC9EZWNvZGVQYXJtczw8L0NvbHVtbnMgNC9QcmVkaWN0b3IgMTIg0K","ProductId":"85c98324-092a-4d10-bab0-03912e437234","OrderId":"7b826322-7526-4a69-b67c-5c88a04f4c60","FileName":"test.pdf","FileType":1,"FileDescription":"test"}

I would like to change this logic to Post as a Content-Type of Multipart. What would be the best way to form my request? Also, what's the best way to structure my Web API Controller to process the Multipart request?

M. Tovbin
  • 537
  • 3
  • 12

1 Answers1

1

This is a sample for a Multipart upload.

    [HttpPost]
    [Route("upload")]
    public async Task<IHttpActionResult> Upload()
    {
        MultipartFileData file = null;

        // Check if the request contains multipart/form-data.
        if (!Request.Content.IsMimeMultipartContent())
        {
            return UnsupportedMediaType();
        }

        // initialize path and provider
        string root = HttpContext.Current.Server.MapPath("~/App_Data");
        if (Directory.Exists(root) == false) Directory.CreateDirectory(root);

        var provider = new MultipartFormDataStreamProvider(root);

        // Read the form data.
        await Request.Content.ReadAsMultipartAsync(provider);

        try
        {
            // we take the first file here
            file = provider.FileData[0];

            // and the associated datas
            int myInteger;
            if (int.TryParse(provider.FormData["MyIntergerData"], out myInteger) == false)
                throw new ArgumentException("myInteger is missing or not valid.");

            var fileContent = File.ReadAllBytes(file.LocalFileName);

            // do something with your file!
        }
        finally
        {
            // get rid of temporary file
            if (file != null)
                File.Delete(file.LocalFileName);
        }

        // successfull!
        return NoContent();
    }

This is a sample I got from an API of mine. You can have multiple files for each upload (check the provider.FileData array), and different datas inside the provider.FormData array.

For the client side aspect of this I suggest you to check this answer for a sample of a JS call to this API.

Hope it helps!

Luca Ghersi
  • 3,261
  • 18
  • 32
  • Thanks for the reply. I am looking to determine what is the best way to form my request that will include the file along with the meta data. Also, I would be looking to store the file into a Filestream file in the SQL DB. What would be the best way to do that with my controller? – M. Tovbin Mar 23 '16 at 02:36
  • I updated my answer with a link to a client side sample of js upload. For the filestram thing it depends on how do you access your data; check this for a little sample using SqlFileStream: https://blogs.msdn.microsoft.com/spike/2011/02/28/inserting-a-file-into-a-filestream-table-from-c-and-how-to-get-it-back-as-well/ – Luca Ghersi Mar 23 '16 at 08:20
  • When using MultipartFormDataStreamProvider is my best bet to temporarily store files in a temporary directory prior to saving them to the Filestream column? Also, if I am doing a POST from Silverlight or UWP would I still use FormData? – M. Tovbin Mar 25 '16 at 16:21