2012-06-20 4 views
66

Używam ASP.NET Web API.
Chcę pobrać plik PDF z C# z API (który generuje API).Microsoft Web Api zwraca plik? użyć bajtu []?

Czy mogę po prostu zwrócić interfejs API byte[]? i dla aplikacji C# I można po prostu zrobić:

byte[] pdf = client.DownloadData("urlToAPI");? 

i

File.WriteAllBytes()? 
+0

„API Web”? Co dokładnie masz na myśli? Przeczytaj http://tinyurl.com/so-hints i edytuj swoje pytanie. –

+1

@ JonSkeet: Web API to nowa funkcja w najnowszej wersji ASP.NET. Zobacz http://www.asp.net/whitepapers/mvc4-release-notes#_Toc317096197 –

+1

@Robert: Dzięki - tag czyni go wyraźniejszym, chociaż nawiązanie do "interfejsu API ASP.NET Web" byłoby jeszcze wyraźniejsze. Częściowo wina MS z powodu banalnie ogólnej nazwy :) –

Odpowiedz

115

Lepiej wrócić HttpResponseMessage z StreamContent wewnątrz niego.

Oto przykład:

public HttpResponseMessage GetFile(string id) 
{ 
    if (String.IsNullOrEmpty(id)) 
     return Request.CreateResponse(HttpStatusCode.BadRequest); 

    string fileName; 
    string localFilePath; 
    int fileSize; 

    localFilePath = getFileFromID(id, out fileName, out fileSize); 

    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); 
    response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read)); 
    response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); 
    response.Content.Headers.ContentDisposition.FileName = fileName; 
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); 

    return response; 
} 

UPD z komentarzem przez patridge: Gdyby ktoś się tu chce wysłać odpowiedź z tablicy bajtów zamiast rzeczywistego pliku, masz zamiar chcesz użyć nowej ByteArrayContent (someData) zamiast StreamContent (patrz here).

+1

Po pierwsze - ten kod spowoduje wyjątek, ponieważ tworzymy dwa obiekty FileStream wskazane na ten sam plik. Drugą sprawą jest to, że nie chcesz używać instrukcji "Używanie", ponieważ gdy tylko zmienna wykracza poza zakres, usługa .NET ją wyrzuci, a otrzymasz komunikat o błędzie dotyczący zamknięcia połączenia. –

+1

@BrandonMontgomery Ok, masz rację. Dzięki! – Regfor

+38

Jeśli ktokolwiek inny chciałby wysłać odpowiedź z tablicy bajtów zamiast rzeczywistego pliku, będziesz chciał użyć 'new ByteArrayContent (someData)' zamiast 'StreamContent' (zobacz [tutaj] (http: //stackoverflow.com/a/12468615/48700)). – patridge

22

że wykonał działanie następujące:

[HttpGet] 
[Route("api/DownloadPdfFile/{id}")] 
public HttpResponseMessage DownloadPdfFile(long id) 
{ 
    HttpResponseMessage result = null; 
    try 
    { 
     SQL.File file = db.Files.Where(b => b.ID == id).SingleOrDefault(); 

     if (file == null) 
     { 
      result = Request.CreateResponse(HttpStatusCode.Gone); 
     } 
     else 
     { 
      // sendo file to client 
      byte[] bytes = Convert.FromBase64String(file.pdfBase64); 


      result = Request.CreateResponse(HttpStatusCode.OK); 
      result.Content = new ByteArrayContent(bytes); 
      result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); 
      result.Content.Headers.ContentDisposition.FileName = file.name + ".pdf"; 
     } 

     return result; 
    } 
    catch (Exception ex) 
    { 
     return Request.CreateResponse(HttpStatusCode.Gone); 
    } 
} 
+0

To faktycznie odpowiada na pytanie – Mick

0

przykład z IHttpActionResult w ApiController.

[HttpGet] 
[Route("file/{id}/")] 
public IHttpActionResult GetFileForCustomer(int id) 
{ 
    if (id == 0) 
     return BadRequest(); 

    var file = GetFile(id); 

    IHttpActionResult response; 
    HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.OK); 
    responseMsg.Content = new ByteArrayContent(file.SomeData); 
    responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); 
    responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName; 
    responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); 
    response = ResponseMessage(responseMsg); 
    return response; 
} 

Jeśli nie chcesz, aby pobrać plik PDF i użyć przeglądarki wbudowanej w przeglądarkę PDF zamiast usunąć następujące dwa wiersze:

responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); 
responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName; 
+0

Jaki jest następny krok? Czy to działa z tym właśnie? –

+0

@ElbertJohnFelipe Tak, otrzymasz plik z 'var file = GetFile (id);'. 'file.SomeData' jest tablicą bajtów (' byte [] ') i' file.FileName'jest 'string'. – Ogglas