2016-07-03 1 views
4

я кнопка определяется как:angular2 загрузка файла с запросом после

<button pButton type="button" label="Download" data-icon="fa-cloud-download" (click)="download()"></button> 

где download метод делегаты на службу, и вызов службы API-интерфейс с помощью метода поста:

download(model:GlobalModel) { 
     let downloadURL = base + "rest/process/download"; 
     let body = JSON.stringify(model); 
     let headers = new Headers({'Content-Type': 'application/json'}); 
     let options = new RequestOptions({headers: headers}); 

     this.http.post('http://localhost:48080/rest/process/download', body, options) 
      .toPromise() 
      .then(
       response => { 
        console.log(response);  
        var mediaType = 'application/zip'; 
        var blob = new Blob([response.blob()], {type: mediaType}); 
        var filename = 'project.zip'; 
        saveAs(blob, filename);//FileSaver.js libray 
       }); 

    } 

Но теперь метод blob() не был реализован, и есть другие ответы с использованием _body, но есть ошибка типа машинописного текста, такая как «_body is private».

Браузер отображает окно загрузки, но когда я загружаю файл, он поврежден и не может его открыть (я проверю с помощью postman и файл сгенерирован с сервера).

Как я могу загрузить файл должным образом? ... если это невозможно, существует обходное решение?

+0

Что произойдет, если вы сделаете это: 'Новый Blob ([response.text()], {Тип: MEDIATYPE})'? 'text()' должен возвращать сырое тело ответа, я считаю .. – Sasxa

+0

'.text()' создает поврежденный файл – Sergio

ответ

3

я, наконец, решить, используя трюк объяснил в ответе: https://stackoverflow.com/a/37051365/2011421

Здесь я описываю здесь свой особый подход только в случае, если:

download(model:GlobalModel) { 
    // Xhr creates new context so we need to create reference to this 
    let self = this; 
    var pending:boolean = true; 

    // Create the Xhr request object 
    let xhr = new XMLHttpRequest(); 

    let url = BASE + "/download"; 
    xhr.open('POST', url, true); 
    xhr.setRequestHeader("Content-type", "application/json"); 
    xhr.responseType = 'blob'; 

    // Xhr callback when we get a result back 
    // We are not using arrow function because we need the 'this' context 
    xhr.onreadystatechange = function() { 

     // We use setTimeout to trigger change detection in Zones 
     setTimeout(() => { 
      pending = false; 
     }, 0); 

     // If we get an HTTP status OK (200), save the file using fileSaver 
     if (xhr.readyState === 4 && xhr.status === 200) { 
      var blob = new Blob([this.response], {type: 'application/zip'}); 
      saveAs(blob, 'project.zip'); 
     } 
    }; 

    // Start the Ajax request 
    xhr.send(JSON.stringify(model)); 
} 

К сожалению angular2 http объекта уже не является полным и этим решением хотя полезно чувствовать себя взломанным.

4

здесь является рабочим облегченный примером https://stackoverflow.com/a/42992377/3752172

Изменить контроллер POST:

[HttpPost("realisationsFilterExcel")] 
public FileResult exportExcell([FromBody] FilterRealisation filter) 
{ 
    var contentType = "application/octet-stream"; 
    HttpContext.Response.ContentType = contentType; 

    PaginationSet<RealisationReportViewModel> itemsPage = _realisationRepository.GetRealisationReportFilter(filter, User); 

    RealisationsReportExcell reportExcell = new RealisationsReportExcell(); 
    var filedata = reportExcell.GetReport(itemsPage); 
    FileContentResult result = new FileContentResult(filedata, contentType) 
    { 
     FileDownloadName = "report.xlsx" 
    }; 
    return result; 
} 

Require FileSaver, как DEP:

npm install file-saver --save 
npm install @types/file-saver --save 

Изменить метод DownloadComponent angular2 к POST

@Input() filter: any; 

public downloadFilePost() { 
     this.http.post(this.api, this.filter, { responseType: ResponseContentType.Blob }) 
     .subscribe(
     (response: any) => { 
      let blob = response.blob(); 
      let filename = 'report.xlsx'; 
      FileSaver.saveAs(blob, filename); 
     }); 
    } 

Использование

<download-btn [filter]="myFilter" api="api/realisations/realisationsFilterExcel"></download-btn> 
+0

работает как шарм. Благодаря! Я просто добавляю FileSaver dep: 'npm install file-saver --save' и' npm install @ types/file-saver --save' cf. https://stackoverflow.com/questions/40240796/angular-2-best-approach-to-use-filesaver-js – boly38

Смежные вопросы