2016-07-27 2 views
3

브라우저에서 파일을 다운로드 할 수 없습니다. 파일을 준비하고 응답 스트림을 출력합니다.엑셀 파일로 응답 다운로드

레스트 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

각도는 파일 내용을 단순한 문자 시퀀스로 받게됩니다. 이러한 문자로 파일을 만들고 프론트 엔드에서 브라우저 다운로드를 시작해야합니다.

당신은 이런 식으로 작업을 수행 할 수 있습니다 -

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

data 당신이 당신의 API를 형성받은 응답입니다. saveAs 함수는 FileSaver.js 라이브러리의 일부입니다. 수동으로 수행하는 방법을 살펴볼 수 있지만 왜 바퀴를 다시 만들 수 있습니까?

+2

나머지 코드의 Response 객체의 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 친절하게 내 fiddle 한번 확인 https://jsfiddle.net/x30v0bym/3/ 파일 다운로드가 올바르게 wokring하지만 Excel에서 제대로 열리지 않습니다 Excel에서 백지 도움말을 사용하여 데이터를 표시하지 않습니다. – jose

+0

@jose 문제는 적절한 형식으로 콘텐츠를 생성하지 않는다는 것입니다. HTML을 파일로 저장하고 * xls * 확장자로 이름을 지정했습니다. 자동으로 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

관련 문제