2

J'essaie de renvoyer un fichier dans un contrôleur ASP.NET Web API. Ce fichier est un fichier PDF généré dynamiquement enregistré dans un MemoryStream.Angular/Web API 2 renvoie un fichier non valide ou corrompu avec StreamContent ou ByteArrayContent

Le client (navigateur) reçoit le fichier avec succès, mais quand j'ouvre le fichier, je vois que toutes les pages sont totalement vides. Le fait est que si je prends le même MemoryStream et l'écris dans un fichier, ce fichier disque est affiché correctement, donc je suppose que le problème est lié au transfert de fichier via le Web.

Mon contrôleur ressemble à ceci:

[HttpGet][Route("export/pdf")] 
public HttpResponseMessage ExportAsPdf() 
{ 
    MemoryStream memStream = new MemoryStream(); 
    PdfExporter.Instance.Generate(memStream); 

    memStream.Position = 0; 
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); 
    result.Content = new ByteArrayContent(memStream.ToArray()); //OR: new StreamContent(memStream); 
    return result; 
} 

Juste pour essayer, si j'écris le flux sur le disque, il est affiché correctement:

[HttpGet][Route("export/pdf")] 
public HttpResponseMessage ExportAsPdf() 
{ 
    MemoryStream memStream = new MemoryStream(); 
    PdfExporter.Instance.Generate(memStream); 

    memStream.Position = 0; 
    using (var fs = new FileStream("C:\\Temp\\test.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite)) 
    { 
     memStream.CopyTo(fs); 
    } 

    return null; 
} 

Les différences sont les suivantes:

  • PDF enregistré sur le disque: 34KB
  • PDF transféré via le Web : 60KB

Si je compare les deux contenu des fichiers, les principales différences sont (!):

File Differences

Sur la gauche est le PDF transféré via le web; sur la droite, le PDF enregistré sur le disque.

Y at-il un problème avec mon code? Peut-être quelque chose en rapport avec les encodages?

Merci!

Répondre

2

Eh bien, il est avéré être un problème client (navigateur), pas un problème de serveur. J'utilise AngularJS dans le frontend, donc quand le respose a été reçu, Angular l'a automatiquement converti en une chaîne Javascript. Dans cette conversion, le contenu binaire du fichier ont été modifiés en quelque sorte ...

Fondamentalement, il a été résolu en disant angulaire de ne pas convertir la réponse à une chaîne:

$http.get(url, { responseType: 'arraybuffer' }) 
.then(function(response) { 
    var dataBlob = new Blob([response.data], { type: 'application/pdf'}); 
    FileSaver.saveAs(dataBlob, 'myFile.pdf'); 
}); 

Et puis enregistrez la réponse en fichier, aidé par le service Angular File Saver.

2

Je Gess vous devez définir ContentDisposition et ContentType comme ceci:

[HttpGet][Route("export/pdf")] 
public HttpResponseMessage ExportAsPdf() 
{ 
    MemoryStream memStream = new MemoryStream(); 
    PdfExporter.Instance.Generate(memStream); 

    var result = new HttpResponseMessage(HttpStatusCode.OK) 
    { 
     Content = new ByteArrayContent(memStream.ToArray()) 
    }; 
    result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") 
    { 
     FileName = "YourName.pdf" 
    }; 
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 
    return result; 
} 
+0

Vous me battez à elle. :) si proche. Votez pour vous. – Nkosi

+0

Désolé mais pas de chance :(Même résultat: 'memStream.GetBuffer()' renvoie un tableau ~ 64K byte, alors que 'memStream.ToArray()' renvoie un tableau ~ 34K byte ... – Adrian

+2

Ne pas utiliser GetBuffer() comme il renvoie un tableau de taille fixe ... utilise ToArray(). –

0

Essayez cette

[HttpGet][Route("export/pdf")] 
public HttpResponseMessage ExportAsPdf() 
{ 
    MemoryStream memStream = new MemoryStream(); 
    PdfExporter.Instance.Generate(memStream); 

    //get buffer 
    var buffer = memStream.GetBuffer(); 
    //content length for header 
    var contentLength = buffer.Length; 

    var statuscode = HttpStatusCode.OK; 
    var response = Request.CreateResponse(statuscode); 
    response.Content = new StreamContent(new MemoryStream(buffer)); 
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); 
    response.Content.Headers.ContentLength = contentLength; 
    ContentDispositionHeaderValue contentDisposition = null; 
    if (ContentDispositionHeaderValue.TryParse("inline; filename=my_filename.pdf", out contentDisposition)) { 
     response.Content.Headers.ContentDisposition = contentDisposition; 
    } 

    return response; 
} 
+0

Malheureusement, le même résultat ... comme si rien ne changeait. – Adrian