2016-07-27 15 views
3

ブラウザでファイルがダウンロードされていません。私はファイルを準備し、それを出力ストリームに書き出します。応答をExcelファイルとしてダウンロード

のREST APIがあります:フロントエンドから

@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(); 
     } 
    } 

(角度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; 
    } 
})(); 

ファイルの内容を非読める形式として反応してあります。しかし、ファイルはブラウザでダウンロードされません。

+0

クロームV52、FFのV48とIEで動作します。 クロムブラウザで動作していましたが、他のブラウザではテストしませんでした – akhilsk

+0

あなたの問題を解決した場合は、受け入れられたものとしてマークしてください。 –

答えて

4

Angularはファイルの内容を単なる文字シーケンスで受け取ります。これらの文字からファイルを作成し、フロントエンドでブラウザのダウンロードを開始する必要があります。

あなたはこのようにそれを行うことができます -

dataはあなたのAPIを形成し、受信した応答である
var blob = new Blob([data], 
        {type: 'application/vnd.openxmlformat-officedocument.spreadsheetml.sheet;'}); 
saveAs(blob, fileName); 

を。 saveAs関数はFileSaver.jsライブラリの一部です。それを手動で行う方法を見ることはできますが、なぜホイールを改革するのでしょうか?

+2

レスポンスオブジェクトの残りのAPIのresponse.build()メソッドから返されたExcelファイルを保存するのに、この同じコードを使用します。ファイルを保存しますが、保存したExcelファイルを開こうとすると、ファイルの破損エラーメッセージが表示されます。 –

+0

これには解決策がありましたか?同じ問題に直面している。 – Chiya

3

XHRを使用してファイルをダウンロードすることは問題です。あなたがGET要求だけを行う限り、ブラウザにファイルをダウンロードさせるためのより簡単なアプローチが存在します。

JavaScriptネイティブメソッドwindow.open(url)を使用してください。 IE9を含むすべてのブラウザで正常に動作します。

以下のコードでは、ネイティブウィンドウオブジェクトのAngularのプロキシである$windowを使用します。このアクションは、角の範囲外であることを

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

注意、あなたはエラー処理やファイルがダウンロードされるまで待っについて多くを行うことはできません。あなたのコードのための

例は次のようである可能性があります。巨大なExcelファイルを生成したい場合、またはAPIが遅い場合は問題になる可能性があります。詳細については

は、質問をお読みください。Spring - download response as a file

アップデート:私は、ファイルをダウンロードするためのより良い選択であるように思わwindow.open()window.location.hrefを交換しました

APIでファイルの代わりにエラーページがスローされた場合は、window.location.hrefが現在のページを置き換えます(そのため、状態が失われます)。 $window.open()ただし、このエラーは新しいタブでアプリケーションの現在の状態を失うことなく開きます。

+0

こんにちは@Piotr Lewandowskiは親切に私のフィドルをチェックしてください。https://jsfiddle.net/x30v0bym/3/ファイルのダウンロードは正しくwokringしていますが、Excelで正しく開くことができません。私は白い紙のヘルプでデータを表示しています。 – jose

+0

@joseあなたの問題は、適切な形式でコンテンツを生成しないということです。あなたはHTMLをファイルに保存しただけで、* xls * extensionという名前を付けました。それは自動的にExcelファイル形式に変換されることはありません。 *別の質問をする*それを行う適切な方法を説明するためにはるかに多くのスペースが必要です。 –

+0

@jose私はすでにあなたに質問しています。私はここに答えました:https://stackoverflow.com/a/44602960/2757140 –

3

新しいタブでファイルをダウンロードできます。最新のブラウザは、ダウンロードが完了すると自動的に閉じます。

新しいウィンドウを開くと、参照が取得されます。ダウンロードが完了すると、window.closedはtrueに設定されます。

不幸にも、このパラメータの内側の間隔を時々チェックする必要があります...

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

は、テストの結果、私は同じコードが、マイナーチェンジresponse.setContentType(「アプリケーション/強制ダウンロード」)を行っている11

関連する問題