Angular $http로 다운로드 받은 파일 이름을 얻는 방법
Angular $http를 사용하여 파일을 다운로드하는 코드를 작성했습니다.URL에 파일 이름이 지정되지 않았습니다.URL 에는, 애플리케이션의 외부로부터 취득한, 파일의 일의의 식별자가 포함됩니다.
언제$http.get(myUrl)
모든 것이 정상적으로 동작합니다.파일은 취득되어 콜백핸들러로 액세스 할 수 있습니다만, 파일명을 취득하는 방법을 알 수 없습니다.Fiddler에서 원시 응답을 캡처하면 다음과 같이 표시됩니다.
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 54
Content-Type: application/octet-stream
Server: Microsoft-IIS/8.5
Access-Control-Allow-Origin: http://www.example.com/getFile/12345
Access-Control-Allow-Credentials: true
Content-Disposition: attachment; filename=testfile.txt
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 09 Oct 2015 20:25:49 GMT
Lorem ipsum dolar sit amet! The contents of my file!
위에서 보면 서버가 "Content-Disposition"에서 파일 이름을 다시 보내고 있는 것이 분명하지만, Angular 콜백 내에서 파일에 액세스할 수 있는 방법을 찾을 수 없습니다.헤더에서 파일 이름을 가져오려면 어떻게 해야 하나요?
아래 답변에 따라 편집:아까도 말씀드렸어야 했는데response.headers()
. 다시 돌아오다Object {content-type: "application/octet-stream", cache-control: "private"}
그래서 어떤 이유로든 콘텐츠 폐기가 되지 않습니다. response.headers('Content-Disposition')
돌아온다null
.
HTTP 헤더에서 파일명을 취득하려면 , 다음의 파일을 추출하는 것을 추천합니다.Content-Disposition
헤더는 충분하지 않습니다.아직 입수할 필요가 있습니다.filename
속성을 지정합니다.
반환되는 헤더 값의 예:attachment; filename="myFileName.pdf"
.
아래 함수는 추출합니다.filename="myFileName.pdf"
, 그 후 추출"myFileName.pdf"
그리고 마지막으로 주변의 여분의 인용문을 지우고myFileName.pdf
.
아래의 스니펫을 사용할 수 있습니다.
function getFileNameFromHttpResponse(httpResponse) {
var contentDispositionHeader = httpResponse.headers('Content-Disposition');
var result = contentDispositionHeader.split(';')[1].trim().split('=')[1];
return result.replace(/"/g, '');
}
웹 API: IHtpActionResult 구현의 ExecuteAsync(...) 메서드에 다음 코드 행을 추가하는 것이 효과가 있음을 발견했습니다('response'는 반환되는 HttpResponseMessage입니다).
response.Content.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
각도:그 후 다음과 같이 각진 파일명을 해결할 수 있었습니다('response'는 $http.get에서 해결된 약속입니다).
var contentDisposition = response.headers('Content-Disposition');
var filename = contentDisposition.split(';')[1].split('filename')[1].split('=')[1].trim();
CORS를 사용하는 경우 서버 측의 응답 헤더에 "Access-Control-Expose-Headers"를 추가해야 합니다.예를 들어 다음과 같습니다.Access-Control-Expose-Headers: x-filename, x-something-else
위의 답변과 비슷하지만 기본적인 RegEx를 사용하여 문제를 해결했습니다.
let fileName = parseFilenameFromContentDisposition(response.headers('Content-Disposition'));
function parseFilenameFromContentDisposition(contentDisposition) {
if (!contentDisposition) return null;
let matches = /filename="(.*?)"/g.exec(contentDisposition);
return matches && matches.length > 1 ? matches[1] : null;
}
사용하다response.headers
http 응답 헤더를 가져오려면:
$http.get(myUrl).then(function (response) {
// extract filename from response.headers('Content-Disposition')
}
// 서비스
downloadFile(params: any): Observable<HttpResponse<any>> {
const url = `https://yoururl....etc`;
return this.http.post<HttpResponse<any>>(
url,
params,
{
responseType: 'blob' as 'json',
observe: 'response' as 'body'
})
.pipe(
catchError(err => throwError(err))
);
}
// 컴포넌트
import * as FileSaver from 'file-saver';
... some code
download(param: any) {
this.service.downloadFile(param).pipe(
).subscribe({
next: (response: any) => {
let fileName = 'file';
const contentDisposition = response.headers.get('Content-Disposition');
if (contentDisposition) {
const fileNameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = fileNameRegex.exec(contentDisposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
}
const fileContent = response.body;
FileSaver.saveAs(fileContent, fileName);
},
error: (error) => {
console.log({error});
}
});
}
즐거운 시간 되세요.
이미 해결 방법을 찾으셨겠지만, 다른 사람이 이 문제를 가지고 있다면 제가 이 답변을 올리겠습니다.
$http 요청에서 성공 콜백 함수에 다음 파라미터를 추가합니다.
$http.get(myUrl).success(function (data, status, headers, config) {
// extract filename from headers('Content-Disposition')
});
한다면response.headers('Content-Disposition')
null을 반환합니다.사용response.headers.**get**('Content-Disposition');
.
이제 @andrew의 스니펫이 잘 작동하게 되었습니다.
success(function(data, status, headers, response,xhr) {
console.log(headers('Content-Disposition'));
}
이 밖에도 좋은 답변이 많이 있습니다.ASP에 대한 대응에 가장 적합한 것은 다음과 같습니다.NET Core 3.1 서버(이것들의 대부분을 가이드로서 사용).
function getFilename() {
const header = response.headers.get("Content-Disposition");
if (!header) {
return null;
}
let matches = /filename=\"?([^;"]+)\"?;?/g.exec(header);
return matches && matches.length > 1 ? matches[1] : null;
}
여기와 다른 스레드에 있는 많은 답변은 OP의 특정 사례를 해결하거나 훨씬 더 일반적입니다.npm 패키지의 기능부터 시작하는 것이 좋다고 생각합니다.하지만 이 패키지가 Angular 12 앱에서 작동하지 않고(이 코멘트와 유사한 시도에도 불구하고) 다른 답변이 제 사례를 만족시키지 못했기 때문에, 저는 또 다른 기능을 만들었습니다.
는 「 」입니다.Tyłe;k Mopka.png
유효한 응답 헤더가 생성됩니다.
content-disposition: attachment; filename="Ty_ek; Mopka.png"; filename*=UTF-8''Ty%C5%82ek%3B%20Mopka.png
ISO-8859-1 iso iso iso9, iso iso iso, iso iso iso iso iso iso iso iso iso iso iso.분할되었을 만 아니라 부호화퍼센트 부호화) decodeURI
않습니다.는 '이러다', '이러다', '이러다', '이러다 '이러다'unescape
). (그것)
솔루션
export function parseContentDispositionFilename(contentDisposition: string): string {
const filename = getFilename(contentDisposition);
if (filename) {
return unescape(decodeURI(filename));
}
else {
throw new Error('content-disposition filename cannot be empty');
}
}
function getFilename(contentDisposition: string): string | undefined {
const filenames = getFilenameParams(contentDisposition);
if (filenames.filenamestar) {
// RFC 6266 4.1 filename* -> RFC 5987 3.2.1 ext-value
return filenames.filenamestar.replace(/^(?<charset>.+)'(?<language>.*)'(?<filename>.+)$/, '$<filename>');
}
else if (filenames.filename) {
// RFC 6266 4.1 filename (possibly quoted)
return filenames.filename.replace(/^"(?<filename>.+)"$/, '$<filename>');
}
else {
return undefined;
}
}
function getFilenameParams(contentDisposition: string): { filenamestar?: string, filename?: string } {
// Split using ; (if not quoted) and skip the first element since it's `disposition-type`
const [, ...dispositionParams] = contentDisposition.split(/(?!\B"[^"]*);\s(?![^"]*"\B)/);
return {
filenamestar: getParamValue('filename\\*', dispositionParams),
filename: getParamValue('filename', dispositionParams),
};
}
function getParamValue(paramName: string, params: string[]): string | undefined {
const regex = new RegExp('^\\s*' + paramName + '=(?<paramValue>.+)\\s*$', 'i');
return params.find(p => p.match(regex)?.groups?.['paramValue']);
}
사용.
this.http.get(/*...*/).pipe(
map(response => {
const contentDisposition = response.headers.get('content-disposition');
if (!contentDisposition) {
throw new Error('content-disposition header not found');
}
const filename = parseContentDispositionFilename(contentDisposition);
/*...*/
(파일은 브라우저에 바이너리 형식으로 저장됩니다.파일명이 클라이언트의 Network/header/Content-Disposition에 있습니다.파일명을 취득할 필요가 있습니다.)
In Server-side code:
node js code-
response.setHeader('Access-Control-Expose-Headers','Content-Disposition');
response.download(outputpath,fileName);
In client-side code:
1)appComponent.ts file
import { HttpHeaders } from '@angular/common/http';
this.reportscomponentservice.getReportsDownload(this.myArr).subscribe((event: any) => {
var contentDispositionData= event.headers.get('content-disposition');
let filename = contentDispositionData.split(";")[1].split("=")[1].split('"')[1].trim()
saveAs(event.body, filename);
});
2) service.ts file
import { HttpClient, HttpResponse } from '@angular/common/http';
getReportsDownload(myArr): Observable<HttpResponse<Blob>> {
console.log('Service Page', myArr);
return this.http.post(PowerSimEndPoints.GET_DOWNLOAD_DATA.PROD, myArr, {
observe: 'response',
responseType: 'blob'
});
}
언급URL : https://stackoverflow.com/questions/33046930/how-to-get-the-name-of-a-file-downloaded-with-angular-http
'programing' 카테고리의 다른 글
JSON.stringify 반환 [] (0) | 2023.02.23 |
---|---|
커스텀 포스트 타입의 「전면」슬래그와 같은 타이틀의 WordPress 페이지가 있다. (0) | 2023.02.23 |
Angular에서 php(워드프레스) 함수를 사용하는 방법JS 부분 파일? (0) | 2023.02.23 |
Express/Node.js 및 Angular를 사용하여 취소된 요청 처리 (0) | 2023.02.23 |
CORS 오류: 요청 헤더 필드 허가가 비행 전 응답의 Access-Control-Allow-Headers에 의해 허용되지 않습니다. (0) | 2023.02.23 |