각도:HttpClient에서 파일을 다운로드하는 방법은 무엇입니까?
백엔드에서 엑셀을 다운로드해야 하는데 파일이 반환되었습니다.
요청을 수행하면 다음 오류가 발생합니다.
유형 오류:스트림이 필요한 위치에 '정의되지 않음'을 제공했습니다.관찰 가능, 약속, 배열 또는 반복 가능을 제공할 수 있습니다.
내 코드는:
this.http.get(`${environment.apiUrl}/...`)
.subscribe(response => this.downloadFile(response, "application/ms-excel"));
get and map(...)을(를) 시도했지만 작동하지 않았습니다.
세부 정보: Angular 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
뭐가 잘못됐나요?
블롭은 백엔드에서 파일 형식과 함께 반환됩니다.다음 기능은 모든 파일 형식 및 팝업 다운로드 창을 허용합니다.
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();
}
)
}
다음과 같은 방법을 사용해 보십시오.
유형: application/ms-message
/**
* 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.');
}
}
Angular 8(최대 13개 테스트)을 사용하고 있기 때문에 다른 응답을 구현하는 데 시간이 좀 걸렸습니다.저는 결국 다음과 같은 코드(하산에서 영감을 많이 받았습니다.
설정할 이름의 경우 머리글은Access-Control-Expose-Headers반드시 포함해야 하는 항목Content-Dispositiondjang 또는 RF로 설정하려면:
http_response = HttpResponse(package, content_type='application/javascript')
http_response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
http_response['Access-Control-Expose-Headers'] = "Content-Disposition"
각도:
// component.ts
// getFileName not necessary, you can just set this as a string if you wish
getFileName(response: HttpResponse<Blob>) {
let filename: string;
try {
const contentDisposition: string = response.headers.get('content-disposition');
const r = /(?:filename=")(.+)(?:;")/
filename = r.exec(contentDisposition)[1];
}
catch (e) {
filename = 'myfile.txt'
}
return filename
}
downloadFile() {
this._fileService.downloadFile(this.file.uuid)
.subscribe(
(response: HttpResponse<Blob>) => {
let filename: string = this.getFileName(response)
let binaryData = [];
binaryData.push(response.body);
let downloadLink = document.createElement('a');
downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: 'blob' }));
downloadLink.setAttribute('download', filename);
document.body.appendChild(downloadLink);
downloadLink.click();
}
)
}
// service.ts
downloadFile(uuid: string) {
return this._http.get<Blob>(`${environment.apiUrl}/api/v1/file/${uuid}/package/`, { observe: 'response', responseType: 'blob' as 'json' })
}
API(Excel 파일)의 Blob 출력 사용
그리고 @twickrincon 대답.
downloadExcel(): void {
const payload = {
order: 'test',
};
this.service.downloadExcel(payload)
.subscribe((res: any) => {
this.blobToFile(res, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Export.xlsx");
});}
blob to file 공통 함수
blobToFile(data: any, type: string, fileName: string) {
const a = document.createElement('a');
document.body.appendChild(a);
a.style.display = 'none';
const blob = new Blob([data], { type: type });
const url = window.URL.createObjectURL(blob);
a.href = url; a.download = fileName; a.click();
window.URL.revokeObjectURL(url);}
Blob to file 함수에서 우리는 첫번째 파라미터를 우리의 Blob 데이터, 파일의 종류, 그리고 확장자 1을 포함한 패스 파일 이름으로 기대합니다. 우리는 html 태그 요소 2를 만들고 있습니다. 그리고 우리는 html 3에 요소를 추가합니다. 그리고 나서 태그 요소 4를 숨깁니다. 그리고 나서 파일과 타입 5로 새로운 blob 객체를 만들 것입니다. 우리는 URL 6으로 변환할 것입니다.우리 태그 7의 href 속성에 대한 URL. 우리는 그것이 다운로드되도록 우리의 URL을 윈도우에서 열고 있습니다.
저는 "포스트를 이용한 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);
}
Node.js로 작성된 API restful 서버에서 Angular 구성 요소 앱으로 간단한 이미지를 다운로드하는 방법이라는 이 대답에 대한 응답을 찾는데 많은 시간을 보낸 후, 저는 마침내 이 웹 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 테스트된 구성 요소 서비스(내 경우 Employee Service):
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);
})
}
제가 늦었나 봐요.하지만 @Hasan의 마지막 대답은 훌륭했습니다.
저는 이것에서 약간의 변경(헤더를 제거하는 것을 허용하지 않음)을 가졌고 성공했습니다.
downloadFile(route: string, filename: string = null): void { // const baseUrl = 'http://myserver/index.php/api'; this.http.get(route, { responseType: 'blob' }).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(); } ) }
용사를 합니다.Blob의 로서.img:
템플릿:
<img [src]="url">
구성 요소:
public url : SafeResourceUrl;
constructor(private http: HttpClient, private sanitizer: DomSanitizer) {
this.getImage('/api/image.jpg').subscribe(x => this.url = x)
}
public getImage(url: string): Observable<SafeResourceUrl> {
return this.http
.get(url, { responseType: 'blob' })
.pipe(
map(x => {
const urlToBlob = window.URL.createObjectURL(x) // get a URL for the blob
return this.sanitizer.bypassSecurityTrustResourceUrl(urlToBlob); // tell Anuglar to trust this value
}),
);
}
단순하게 유지하세요, 저는 제안된 모든 복잡한 해결책에 놀랐습니다.
할 attachment와 국기filename그재산에 있는 Content-Disposition당신은 간단하게 이 자바스크립트 호출을 할 수 있습니다.
window.location = `${environment.apiUrl}/...`;
브라우저가 현재 페이지를 변경하지 않고 파일을 다운로드합니다.
언급URL : https://stackoverflow.com/questions/51682514/angular-how-to-download-a-file-from-httpclient
'programing' 카테고리의 다른 글
| '서버를 사용할 수 없습니다' 서버의 MSDTC (0) | 2023.08.06 |
|---|---|
| 테이블에 값 삽입 Oracle SQL (0) | 2023.08.06 |
| 저장 프로시저 SQLWARN 종료 처리기가 호출되지 않았습니다. (0) | 2023.08.06 |
| php로 일반 텍스트 파일 읽기 (0) | 2023.08.06 |
| 덱스를 병합할 수 없습니다. (0) | 2023.08.01 |