web-dev-qa-db-ja.com

角度:HttpClientからファイルをダウンロードする方法は?

バックエンドからExcelをダウンロードする必要があります。ファイルが返されます。

要求を行うと、エラーが発生します。

TypeError:ストリームが予想される場所に「未定義」を指定しました。 Observable、Promise、Array、またはIterableを提供できます。

私のコードは:

this.http.get(`${environment.apiUrl}/...`)
      .subscribe(response => this.downloadFile(response, "application/ms-Excel"));

Getとmap(...)を試みましたが、うまくいきませんでした。

詳細:角度5.2

参照:

import { HttpClient } from '@angular/common/http';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/finally';
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/catch';

応答のコンテンツタイプ:

Content-Type: application/ms-Excel

どうしましたか?

14
Jean Carlos

次のようなものを試してください:

タイプ:application/ms-Excel

/**
 *  used to get file from server
 */

this.http.get(`${environment.apiUrl}`,{
          responseType: 'arraybuffer',headers:headers} 
         ).subscribe(response => this.downLoadFile(response, "application/ms-Excel"));


    /**
     * Method is use to download file.
     * @param data - Array Buffer data
     * @param type - type of the document.
     */
    downLoadFile(data: any, type: string) {
        let blob = new Blob([data], { type: type});
        let url = window.URL.createObjectURL(blob);
        let pwa = window.open(url);
        if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
            alert( 'Please disable your Pop-up blocker and try again.');
        }
    }
25
UnluckyAj

BLOBは、バックエンドからファイルタイプとともに返されます。次の関数は、任意のファイルタイプとポップアップダウンロードウィンドウを受け入れます。

downloadFile(route: string, filename: string = null): void{

    const baseUrl = 'http://myserver/index.php/api';
    const token = 'my JWT';
    const headers = new HttpHeaders().set('authorization','Bearer '+token);
    this.http.get(baseUrl + route,{headers, responseType: 'blob' as 'json'}).subscribe(
        (response: any) =>{
            let dataType = response.type;
            let binaryData = [];
            binaryData.Push(response);
            let downloadLink = document.createElement('a');
            downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, {type: dataType}));
            if (filename)
                downloadLink.setAttribute('download', filename);
            document.body.appendChild(downloadLink);
            downloadLink.click();
        }
    )
}
15
Hasan

この答えへの応答を探すのに多くの時間を費やした後:Node.jsで書かれたAPIの安らかなサーバーからAngularコンポーネントアプリに簡単な画像をダウンロードする方法、私はついにこのWebで美しい答えを見つけました- Angular HttpClient Blob 。基本的には次のもので構成されます。

API Node.js restful:

   /* After routing the path you want ..*/
  public getImage( req: Request, res: Response) {

    // Check if file exist...
    if (!req.params.file) {
      return res.status(httpStatus.badRequest).json({
        ok: false,
        msg: 'File param not found.'
      })
    }
    const absfile = path.join(STORE_ROOT_DIR,IMAGES_DIR, req.params.file);

    if (!fs.existsSync(absfile)) {
      return res.status(httpStatus.badRequest).json({
        ok: false,
        msg: 'File name not found on server.'
      })
    }
    res.sendFile(path.resolve(absfile));
  }

Angular 6がテストしたコンポーネントサービス(私の場合はEmployeeService):

  downloadPhoto( name: string) : Observable<Blob> {
    const url = environment.api_url + '/storer/employee/image/' + name;

    return this.http.get(url, { responseType: 'blob' })
      .pipe(
        takeWhile( () => this.alive),
        filter ( image => !!image));
  }

テンプレート

 <img [src]="" class="custom-photo" #photo>

コンポーネントサブスクライバおよび使用:

@ViewChild('photo') image: ElementRef;

public LoadPhoto( name: string) {
    this._employeeService.downloadPhoto(name)
          .subscribe( image => {
            const url= window.URL.createObjectURL(image);
            this.image.nativeElement.src= url;
          }, error => {
            console.log('error downloading: ', error);
          })    
}
2
Marc

「投稿を使用してrxjsダウンロードファイル」を検索すると、ここで終了しました。

これが私の最終製品でした。サーバーの応答で指定されたファイル名とタイプを使用します。

import { ajax, AjaxResponse } from 'rxjs/ajax';
import { map } from 'rxjs/operators';

downloadPost(url: string, data: any) {
    return ajax({
        url: url,
        method: 'POST',
        responseType: 'blob',
        body: data,
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'text/plain, */*',
            'Cache-Control': 'no-cache',
        }
    }).pipe(
        map(handleDownloadSuccess),
    );
}


handleDownloadSuccess(response: AjaxResponse) {
    const downloadLink = document.createElement('a');
    downloadLink.href = window.URL.createObjectURL(response.response);

    const disposition = response.xhr.getResponseHeader('Content-Disposition');
    if (disposition) {
        const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        const matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) {
            const filename = matches[1].replace(/['"]/g, '');
            downloadLink.setAttribute('download', filename);
        }
    }

    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
}
0
Mikael