2017-06-09 9 views
1

私は、REST APIからファイルの内容を取得し、クライアントにファイルを生成する必要があるAngularアプリを持っています。バイナリファイルをAngularで作成する

クライアントに新しいファイルを書き込めないため、回避策としてthis questionを使用します。

基本的には、内容を含むBLOBを作成してダウンロードリンクを生成し、リンク内のクリックをシミュレートしてドキュメントがダウンロードされるようにします。

これは私のコードです:

download(filename) { 
    this.service 
     .downloadFile(filename) 
     .subscribe(data => { 
     console.log(data.document); 
     this.downloadFile(data.document, filename); 
     }, err => this.info = err); 
    } 

これは、サーバー

private downloadFile(content: string, filename: string) { 
    const link = document.createElement('a'); 
    link.setAttribute('download', filename); 
    link.href = this.makeTextFileUrl(content, filename); 

    document.body.appendChild(link); 

    // wait for the link to be added to the document 
    window.requestAnimationFrame(function() { 
     const event = new MouseEvent('click'); 
     link.dispatchEvent(event); 
     document.body.removeChild(link); 
    }); 
    } 

からデータを取得し、これはリンクを構築し、これが発生

private makeTextFileUrl(content: string, filename: string): string { 
    let url = null; 

    const mime = this.getMimeType(filename); 
    console.log(mime); 
    const blob = new Blob([content], { type: mime }); 
    // If we are replacing a previously generated file we need to 
    // manually revoke the object URL to avoid memory leaks. 
    if (url !== null) { 
     window.URL.revokeObjectURL(url); 
    } 

    url = window.URL.createObjectURL(blob); 
    return url; 
    } 

をダウンロードするにはクリックをシミュレートURLリンク

private getMimeType(filename: string): string { 
    if (filename.indexOf('.docx') !== -1) return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; 
    if (filename.indexOf('.doc') !== -1) return 'application/msword'; 
    if (filename.indexOf('.pdf') !== -1) return 'application/pdf'; 
    return 'text/plain'; 
    } 

MIMEタイプは、拡張子ので

によって異なり、これはテキストファイルのために動作しますが、私は、ファイルを開こうとすると、私はエラーを取得するdocxファイルのファイルに対してとPDFでファイルが空白のようです。

私はバイナリファイルのために、私はこれが動作するためにArrayBufferにresponseTypeを設定する必要があるので、私はこの

downloadFile(id: string): Observable<any> { 
    return this.authHttp 
     .get(`${this.api}/download/${id}`, { responseType: ResponseContentType.ArrayBuffer }) 
     .map(res => { 
     const data = res.json(); 
     return data; 
     }); 
    } 

に呼び出します私のサービスを更新しましたが、私はダウンロードしようとすると、今、私はエラーを取得することを読ん

txt、pdfまたはdocxファイルであるかどうかにかかわらず、ファイルSyntaxError: Unexpected token ≻ in JSON at position 0

これを修正する方法を知っている人はいますか?

ありがとうございました

答えて

0

私はついにこれを動作させました。

中間のAPI Restを使用してファイルの内容を取得してからフロントエンドアプリに再送信することが判明しましたが、その手順では本体が文字列として解析されていました私のフロントエンドアプリは元のコンテンツではありませんでした。

このスレッドでは、この問題の修正です。 Resend body from response exactly as it comes

は、その後、私はちょうどバイナリファイルを取得するために私のフロントエンドアプリでいくつかのことを変更しなければなりませんでした。

downloadFile(id: string): Observable<any> { 
    return this.authHttp 
     .get(`${this.api}/${id}`, { responseType: ResponseContentType.ArrayBuffer }) 
     .map(res => { 
     return res.blob(); 
     }); 
    } 

これで、jsonではなくblobとしてデータを取得しています。

その後、私のコンポーネントで

download(filename) { 
    const id = this.filesIds[filename]; 
    this.service 
     .downloadFile(id) 
     .subscribe(blob => { 
     this.downloadFile(blob, filename); 
     }, err => this.info = err); 
    } 

    private downloadFile(blob: Blob, filename: string) { 
    const link = document.createElement('a'); 
    link.setAttribute('download', filename); 

    link.href = this.makeTextFileUrl(blob, filename); 

    document.body.appendChild(link); 

    // wait for the link to be added to the document 
    window.requestAnimationFrame(function() { 
     const event = new MouseEvent('click'); 
     link.dispatchEvent(event); 
     document.body.removeChild(link); 
    }); 
    } 

残りの部分は同じまま。

関連する問題