Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send zip files to ASP.NET WebApi

I'm wondering how I can send a zip file to a WebApi controller and vice versa. The problem is that my WebApi uses json to transmit data. A zip file is not serializable, either is a stream. A string would be serializable. But there has to be an other solution than to convert the zip into a string and than send the string. That just sounds wrong.

Any idea how this is done?

like image 730
Oliver Müller Avatar asked Mar 04 '14 15:03

Oliver Müller


2 Answers

If your API method expects an HttpRequestMessage then you can pull the stream from that:

public HttpResponseMessage Put(HttpRequestMessage request)
{
    var stream = GetStreamFromUploadedFile(request);

    // do something with the stream, then return something
}

private static Stream GetStreamFromUploadedFile(HttpRequestMessage request)
{
    // Awaiting these tasks in the usual manner was deadlocking the thread for some reason.
    // So for now we're invoking a Task and explicitly creating a new thread.
    // See here: http://stackoverflow.com/q/15201255/328193
    IEnumerable<HttpContent> parts = null;
    Task.Factory
        .StartNew(() => parts = request.Content.ReadAsMultipartAsync().Result.Contents,
                        CancellationToken.None,
                        TaskCreationOptions.LongRunning,
                        TaskScheduler.Default)
        .Wait();

    Stream stream = null;
    Task.Factory
        .StartNew(() => stream = parts.First().ReadAsStreamAsync().Result,
                        CancellationToken.None,
                        TaskCreationOptions.LongRunning,
                        TaskScheduler.Default)
        .Wait();
    return stream;
}

This works for me when posting an HTTP form with enctype="multipart/form-data".

like image 119
David Avatar answered Oct 23 '22 06:10

David


Try using a simple HttpResponseMessage, with a StreamContent inside to GET, download file

public HttpResponseMessage Get()
{
    var path = @"C:\Temp\file.zip";
    var result = new HttpResponseMessage(HttpStatusCode.OK);
    var stream = new FileStream(path, FileMode.Open);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentType = 
        new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                            {
                                FileName = "file.zip"
                            };
    return result;
}

and for POST, upload file

public Task<HttpResponseMessage> Post()
{
    HttpRequestMessage request = this.Request;
    if (!request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }


    var provider = new MultipartFormDataStreamProvider("C:\Temp");

    var task = request.Content.ReadAsMultipartAsync(provider).
        ContinueWith<HttpResponseMessage>(o =>
        {

            string file1 = provider.BodyPartFileNames.First().Value;
            // this is the file name on the server where the file was saved 

            return new HttpResponseMessage()
            {
                Content = new StringContent("File uploaded.")
            };
        }
    );
    return task;
}
like image 32
Maxim Nikonov Avatar answered Oct 23 '22 05:10

Maxim Nikonov