2017-08-24 2 views
0

Je n'arrive pas à faire fonctionner le logiciel pour télécharger un fichier Excel créé par closedxml via l'API web. Si je sauvegarde le fichier sur le serveur, il semble bon, mais dès que je le mets dans un flux et le renvoie à l'API Web, seul un fichier corrompu est reçu dans le navigateur.Téléchargement de fichier Excel à partir d'une API Web à l'aide de closedxml

Comme suggéré sur plusieurs articles j'utilise httpResponseMessage, mais aussi dans le navigateur le nom de fichier dans l'en-tête n'arrive jamais.

Nous utilisons:

"Microsoft.AspNet.WebApi" version = "5.2.3" "version = "targetFramework =" net461

" de ClosedXML 0.88.0" targetFramework = "net461"

code WebAPI:

var wb = new XLWorkbook(); 
      var ws = wb.Worksheets.Add("Parcel List"); 


      MemoryStream fs = new MemoryStream(); 
      wb.SaveAs(fs); 
      fs.Position = 0; 


      HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); 
      result.Content = new ByteArrayContent(fs.GetBuffer()); 
      result.Content.Headers.ContentLength = fs.Length; 
      result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") 
      { 
       FileName = "List" + "_" + DateTime.Now.ToShortDateString() + ".xlsx" 
      }; 
      result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 

      return result; 

Voici le code javascript:

context.$http.post(config.get_API_URL() + 'api_call', excel_list, 
     {responseType: 'application/octet-stream'}) 
    .then(
    success_function, 
    error_function) 
} 

success_function:

function(response) { 

        var headers = response.headers; 
       var blob = new Blob([response.body], 
            {type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}, 
            ); 

       window.open(window.URL.createObjectURL(blob)); 

       } 
+0

Si vous enregistrez le fichier, renommez-le en .zip, pouvez-vous l'ouvrir? J'essaie de déterminer si les internes sont corrompus ou si l'emballage est corrompu dans le transfert. –

+0

J'ai enregistré le classeur sur le serveur et l'ai renommé en .zip, il est possible de l'ouvrir et de voir la structure. Donc, il semble être le transfert qui le corrompt – TwoHeadedSquirrel

+0

Si vous pouvez ouvrir le fichier .zip, ce n'est pas le transfert qui l'a corrompu. Pouvez-vous vérifier la longueur du contenu par rapport à la longueur exacte du fichier lorsque vous l'enregistrez sur le serveur? –

Répondre

0

Le problème semble être que le type de réponse pour l'appel api web doit être {responseType: « ArrayBuffer »} au lieu de {responseType : 'application/octet-stream'}

context.$http.post('api-url', excel_list, {responseType: 'arraybuffer'}) .then( success_function, error_function) }

Merci en tout cas pour votre aide rapide

0

Jetez un oeil à l'emballage d'extension Mvc à https://www.nuget.org/packages/ClosedXML.Extensions.Mvc/

PS: On m'a dit que je dois démentir ce à chaque fois. Je suis le mainteneur de ClosedXML et de ClosedXML.Extensions.Mvc.

+0

Malheureusement, cela ne fonctionne pas non plus. Nous utilisons l'API Web et non MVC. Je reçois le même résultat dans le javascript, également avec le "FileStreamResult" de cette extension. – TwoHeadedSquirrel

+0

Ok. Je surveillerai cette question et s'il y a une solution, je l'ajouterai à cette extension. –

0

Je pouvais télécharger avec succès un classeur avec ce code maintenant:

using ClosedXML.Excel; 
using System.IO; 
using System.Net; 
using System.Net.Http; 
using System.Net.Http.Headers; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Web.Http; 

namespace ClosedXML.Extensions.WebApi.Controllers 
{ 
    public class ValuesController : ApiController 
    { 
     public IHttpActionResult Get(int id) 
     { 
      return new TestFileActionResult(id); 
     } 
    } 

    public class TestFileActionResult : IHttpActionResult 
    { 
     public TestFileActionResult(int fileId) 
     { 
      this.FileId = fileId; 
     } 

     public int FileId { get; private set; } 

     public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
     { 
      HttpResponseMessage response = null; 

      var ms = new MemoryStream(); 
      using (var wb = new XLWorkbook()) 
      { 
       var ws = wb.AddWorksheet("Sheet1"); 
       ws.FirstCell().Value = this.FileId; 

       wb.SaveAs(ms); 

       ms.Seek(0, SeekOrigin.Begin); 

       response = new HttpResponseMessage(HttpStatusCode.OK); 
       response.Content = new StreamContent(ms); 
       response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"); 
       response.Content.Headers.ContentDisposition.FileName = "test.xlsx"; 
       response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); 

       response.Content.Headers.ContentLength = ms.Length; 
       ms.Seek(0, SeekOrigin.Begin); 
      } 

      return Task.FromResult(response); 
     } 
    } 
} 
+0

Merci, mais comment la partie javascript recherche-t-elle l'appel sur le Web et le téléchargement lui-même? Avoir le sentiment qu'il y a le problème. – TwoHeadedSquirrel

+0

Je ne suis pas un expert JavaScript. Mais regardez le Q & A dans https://stackoverflow.com/a/24129082/179494. On dirait qu'il y a un soutien varié pour ce que vous essayez de faire. Ma recommandation est d'essayer d'utiliser une balise '' directement au lieu de télécharger le fichier avec un appel AJAX –