Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receive, send file over Web Api

I'm trying to write a WebApi service that receives a file, does a trivial manipulation, and sends the file back. I'm having issues on sending and/or receiving the file from the service.

The issue I'm having is that the file returned from the service is ~1.5x larger than the manipulated file, e.g. when the file is returned it's like 300kb instead of the 200kb it should be.

I assume its being wrapped and or manipulated somehow, and I'm unsure of how to receive it properly. The code for the WebAPI service and the method that calls the web service are included below

In, the WebApi service, when I hit the line return Ok(bufferResult), the file is a byte[253312]

In the method that calls the web service, after the file is manipulated and returned, following the line var content = stream.Result;, the stream has a length of 337754 bytes.

Web API service code

public ConversionController: APIController{
  public async Task<IHttpActionResult> TransformImage()
   {
    if (!Request.Content.IsMimeMultipartContent())
        throw new Exception();

    var provider = new MultipartMemoryStreamProvider();
    await Request.Content.ReadAsMultipartAsync(provider);

    var file = provider.Contents.First();
    var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
    var buffer = await file.ReadAsByteArrayAsync();
    var stream = new MemoryStream(buffer);

// [file manipulations omitted;]
    // [the result is populated into a MemoryStream named response ]

    //debug : save memory stream to disk to make sure tranformation is successfull
    /*response.Position  = 0;
      path = @"C:\temp\file.ext";
      using (var fileStream = System.IO.File.Create(path))
      {
        saveStream.CopyTo(fileStream);
      }*/


    var bufferResult = response.GetBuffer();
    return Ok(bufferResult);
   }
}

Method Calling the Service

public async Task<ActionResult> AsyncConvert()
    {

    var url = "http://localhost:49246/api/conversion/transformImage";   
var filepath = "drive/file/path.ext";
    HttpContent fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(filepath));

    using (var client = new HttpClient())
    {
        using (var formData = new MultipartFormDataContent())
        {
            formData.Add(fileContent, "file", "fileName");

    //call service
            var response = client.PostAsync(url, formData).Result;

            if (!response.IsSuccessStatusCode)
            {
                throw new Exception();
            }
            else
            {

                if (response.Content.GetType() != typeof(System.Net.Http.StreamContent))
                    throw new Exception();

                var stream = response.Content.ReadAsStreamAsync();
                var content = stream.Result;

                var path = @"drive\completed\name.ext";
                using (var fileStream = System.IO.File.Create(path))
                {
                    content.CopyTo(fileStream);  
                }
            }
        }


    }

    return null;
}

I'm still new to streams and WebApi, so I may be missing something quite obvious. Why are the file streams different sizes? (eg. is it wrapped and how do I unwrap and/or receive the stream)

like image 932
monkeyhouse Avatar asked Dec 29 '13 01:12

monkeyhouse


People also ask

Can an API send a file?

Transferring Files with APIs RESTful HTTP based APIs are the current 'go-to' approach for designing applications and file upload and download is a common business requirement for many applications. Files can be streamed attachments or links to the actual content.

CAN REST API transfer files?

Use the File transfer REST API to upload and download files using HTTP or HTTPS as the transport protocol and to list the contents of a directory. Uploads a file to any back-end application that supports REST APIs over HTTP or HTTPS protocol.


1 Answers

okay, to receive the file correctly, I needed to replace the line

var stream = response.Content.ReadAsStreamAsync();

with

var contents = await response.Content.ReadAsAsync<Byte[]>();

to provide the correct type for the binding

so, the later part of the methods that calls the service looks something like

var content = await response.Content.ReadAsAsync<Byte[]>();
var saveStream = new MemoryStream(content);
saveStream.Position = 0;

//Debug: save converted file to disk
/*
var path = @"drive\completed\name.ext";
using (var fileStream = System.IO.File.Create(path))
{
     saveStream.CopyTo(fileStream);  
}*/
like image 132
monkeyhouse Avatar answered Oct 31 '22 09:10

monkeyhouse