2014-03-04 2 views
6

Ich frage mich, wie ich eine ZIP-Datei an einen WebApi-Controller senden kann und umgekehrt. Das Problem ist, dass mein WebApi Json verwendet, um Daten zu übertragen. Eine Zip-Datei ist nicht serialisierbar, auch kein Stream. Eine Zeichenfolge wäre serialisierbar. Aber es muss eine andere Lösung geben, als die Zip in eine Zeichenfolge zu konvertieren und dann die Zeichenfolge zu senden. Das klingt einfach falsch.So senden Sie ZIP-Dateien an ASP.NET WebApi

Eine Idee, wie das gemacht wird?

+3

Wenn Sie eine Binärdatei benötigen, warum sollten Sie sich darauf beschränken, nur JSON zuzulassen? WebApi unterstützt mehrere Möglichkeiten zum Lesen von Binärdateien, entweder über multipart oder einen rohen Byte-Stream. –

Antwort

4

Wenn Ihr API-Methode erwartet ein HttpRequestMessage dann können Sie ziehen der Strom davon:

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; 
} 

Das funktioniert für mich wenn pos ein HTTP-Formular mit enctype="multipart/form-data".

+0

das löste das Problem für mich. Vielen Dank! –

4

Versuchen Sie, eine einfache HttpResponseMessage verwenden, mit einem StreamContent nach innen zu erhalten, Download-Datei

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; 
} 

und für POST, laden Datei

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; 
}