2016-07-27 16 views
3

Die Datei wird nicht im Browser heruntergeladen. Ich bereite die Datei vor und schreibe sie in den Ausgabestream der Antwort.Antwort als Excel-Datei herunterladen

REST-API gibt es:

@RequestMapping(value = "/export-companies", 
     method = {RequestMethod.GET, RequestMethod.HEAD}) 
    @Timed 
    public void downloadCompanies(HttpServletResponse response) throws URISyntaxException { 
     HSSFWorkbook workbook = new HSSFWorkbook(); 
     HSSFSheet sheet = workbook.createSheet("Sample sheet"); 

     Map<String, Object[]> data = new HashMap<String, Object[]>(); 
     data.put("1", new Object[] {"Emp No.", "Name", "Salary"}); 
     data.put("2", new Object[] {1d, "John", 1500000d}); 
     data.put("3", new Object[] {2d, "Sam", 800000d}); 
     data.put("4", new Object[] {3d, "Dean", 700000d}); 

     Set<String> keyset = data.keySet(); 
     int rownum = 0; 
     for (String key : keyset) { 
      Row row = sheet.createRow(rownum++); 
      Object [] objArr = data.get(key); 
      int cellnum = 0; 
      for (Object obj : objArr) { 
       Cell cell = row.createCell(cellnum++); 
       if(obj instanceof Date) 
        cell.setCellValue((Date)obj); 
       else if(obj instanceof Boolean) 
        cell.setCellValue((Boolean)obj); 
       else if(obj instanceof String) 
        cell.setCellValue((String)obj); 
       else if(obj instanceof Double) 
        cell.setCellValue((Double)obj); 
      } 
     } 

     try { 
      ByteArrayOutputStream outByteStream = new ByteArrayOutputStream(); 
      workbook.write(outByteStream); 
      byte [] outArray = outByteStream.toByteArray(); 
      response.setContentType("application/ms-excel"); 
      response.setContentLength(outArray.length); 
      response.setHeader("Expires:", "0"); // eliminates browser caching 
      response.setHeader("Content-Disposition", "attachment; filename=template.xls"); 
      OutputStream outStream = response.getOutputStream(); 
      outStream.write(outArray); 
      outStream.flush(); 
      workbook.close(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

Von Frontend (mit Angular JS):

(function() { 
    'use strict'; 

    angular 
     .module('MyApp') 
     .factory('CompanyExportService', CompanyExportService); 

    CompanyExportService.$inject = ['$resource']; 

    function CompanyExportService ($resource) { 
     var service = $resource('api/export-companies', {}, { 
      'get': { 
       method: 'GET', 
       isArray: false 
      } 
     }); 

     return service; 
    } 
})(); 

Datei-Inhalten gibt es in Antwort als nicht-lesbares Format. Aber Datei wird nicht im Browser heruntergeladen.

+0

ich den gleichen Code getan haben, aber eine geringfügige Änderung response.setContentType ("application/force-download"); hat es in Chrome Browser funktioniert, ich habe nicht in anderen Browsern getestet – akhilsk

+0

Bitte markieren Sie eine Antwort als akzeptiert, wenn es Ihr Problem löst. –

Antwort

4

Angular erhält den Dateiinhalt nur Zeichenfolgen. Sie müssen eine Datei aus diesen Zeichen erstellen und den Browser-Download im Frontend starten.

Sie können es so machen -

var blob = new Blob([data], 
        {type: 'application/vnd.openxmlformat-officedocument.spreadsheetml.sheet;'}); 
saveAs(blob, fileName); 

wo data die Antwort ist, dass Sie Ihre API erhalten bilden. Die saveAs Funktion ist Teil der FileSaver.js Bibliothek. Obwohl Sie sehen können, wie man das manuell macht, aber warum das Rad neu erfinden?

+2

Ich benutze den gleichen Code zum Speichern von Excel-Datei, die von response.build() -Methode von Response-Objekt von Rest API zurückgegeben. Obwohl es Datei speichern, aber während ich versuche, die gespeicherte Excel-Datei zu öffnen, zeigen sie eine beschädigte Datei Fehlermeldung. –

+0

Haben Sie eine Lösung dafür bekommen? bin mit dem gleichen Problem konfrontiert. – Chiya

3

Das Herunterladen von Dateien mit XHR ist problematisch. Solange Sie nur GET-Anfragen durchführen, gibt es einen viel einfacheren Ansatz, um den Browser zum Herunterladen der Datei zu veranlassen.

Verwenden Sie die native JavaScript-Methode . Es funktioniert gut in allen Browsern einschließlich IE9.

Im Code unten verwende ich , die Angulars Proxy für natives Fensterobjekt ist.

Beispiel für Ihren Code könnte wie:

(function() { 
'use strict'; 

angular 
    .module('MyApp') 
    .factory('CompanyExportService', CompanyExportService); 

CompanyExportService.$inject = ['$window']; 

function CompanyExportService ($window) { 
    var exportUrl = 'api/export-companies'; 

    return { 
     download: download 
    } 

    function download() { 
     $window.open(exportUrl); 
    } 
} 
})(); 

Beachten Sie, dass diese Aktion außerhalb des Bereichs von Angular ist, können Sie nicht viel tun können, um die Fehlerbehandlung oder warten, bis die Datei heruntergeladen werden. Könnte ein Problem sein, wenn Sie riesige Excel-Dateien generieren möchten oder Ihre API langsam ist.

Für weitere Details lesen Frage: Spring - download response as a file

Update:

I window.location.href mit window.open() ersetzt haben, die bessere Wahl für das Herunterladen von Dateien zu sein scheint.

Wenn Ihre API eine Fehlerseite anstelle einer Datei auslöst, ersetzt window.location.href die aktuelle Seite (und verliert dadurch ihren Status). jedoch wird dieser Fehler in der neuen Registerkarte geöffnet, ohne den aktuellen Status der Anwendung zu verlieren.

+0

hi @Piotr Lewandowski bitte überprüfen Sie meine Geige einmal https://jsfiddle.net/x30v0bym/3/ Datei-Download ist korrekt, aber Excel nicht ordnungsgemäß öffnen in Microsoft Excel ich bin nicht bekommen Zellen es ist zeigen Daten mit Hilfe von Weißbuch – jose

+0

@jose Ihr Problem besteht darin, dass Sie keinen Inhalt in einem geeigneten Format generieren. Sie haben HTML nur in einer Datei gespeichert und mit der Erweiterung * xls * benannt. Es wird nicht automatisch in das Excel-Dateiformat konvertiert. * Stellen Sie eine andere Frage *, da viel mehr Platz benötigt wird, um die richtige Vorgehensweise zu beschreiben. –

+0

@jose Ich habe festgestellt, dass Sie bereits eine Frage gestellt haben. Ich habe es hier beantwortet: https://stackoverflow.com/a/44602960/2757140 –

3

Sie können die Datei in einem neuen Tab herunterladen. Der moderne Browser schließt sie automatisch, wenn der Download abgeschlossen ist.

Durch Öffnen eines neuen Fensters erhalten Sie einen Hinweis darauf, wenn der Download abgeschlossen ist, dann wird window.closed auf True gesetzt.

Leider müssen Sie von Zeit zu Zeit diesen Parameter innerhalb Intervall überprüfen ...

var newWindowRef = $window.open(url, name); 
if (newWindowRef) { 
    if (newWindowRef.document.body) { // not working on IE 
     newWindowRef.document.title = "Downloading ..."; 
     newWindowRef.document.body.innerHTML = '<h4>Your file is generating ... please wait</h4>'; 
    } 

    var interval = setInterval(function() { 
     if (!!newWindowRef.closed) { 
      // Downloading completed 
      clearInterval(interval); 
     } 
    }, 1000); 
} else { 
    $log.error("Opening new window is probably blocked"); 
} 

geprüft und Arbeiten auf Chrome v52, FF v48 und IE 11