콘텐츠 디스포지션에서 파일 이름을 가져오는 방법
저는 Ajax의 응답으로 파일을 다운받았습니다.에서 파일 이름과 파일 형식을 가져오는 방법content-disposition
썸네일을 표시합니다.검색 결과가 많이 나왔는데 길을 제대로 못 찾았어요.
$(".download_btn").click(function () {
var uiid = $(this).data("id2");
$.ajax({
url: "http://localhost:8080/prj/" + data + "/" + uiid + "/getfile",
type: "GET",
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
},
success: function (response, status, xhr) {
var header = xhr.getResponseHeader('Content-Disposition');
console.log(header);
}
});
콘솔 출력:
inline; filename=demo3.png
옛날에는 이렇게 사용했어요.서버 응답으로 첨부 파일을 제공한다고 가정합니다.
REST 서비스에서 응답 헤더를 이렇게 설정했습니다.response.setHeader("Content-Disposition", "attachment;filename=XYZ.csv");
function(response, status, xhr){
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, '');
}
}
}
편집: 질문에 맞게 답변 편집 - 단어 사용inline
대신attachment
function(response, status, xhr){
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('inline') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, '');
}
}
}
이것은 Marjon4의 답변을 개선한 것입니다.
선택한 답변에 대한 훨씬 간단한 방법은 다음과 같이 분할을 사용하는 것입니다.
var fileName = xhr.getResponseHeader('content-disposition').split('filename=')[1].split(';')[0];
주의: 파일 이름 자체에 세미콜론(;)이 포함되어 있는 경우 이 솔루션은 예상대로 작동하지 않을 수 있습니다.
파일명을 취득해, 이러한 이상한 URL 부호화 UTF-8 헤더와 ASCII 헤더를 서포트하는 경우는, 다음과 같은 것을 사용할 수 있습니다.
public getFileName(disposition: string): string {
const utf8FilenameRegex = /filename\*=UTF-8''([\w%\-\.]+)(?:; ?|$)/i;
const asciiFilenameRegex = /^filename=(["']?)(.*?[^\\])\1(?:; ?|$)/i;
let fileName: string = null;
if (utf8FilenameRegex.test(disposition)) {
fileName = decodeURIComponent(utf8FilenameRegex.exec(disposition)[1]);
} else {
// prevent ReDos attacks by anchoring the ascii regex to string start and
// slicing off everything before 'filename='
const filenameStart = disposition.toLowerCase().indexOf('filename=');
if (filenameStart >= 0) {
const partialDisposition = disposition.slice(filenameStart);
const matches = asciiFilenameRegex.exec(partialDisposition );
if (matches != null && matches[2]) {
fileName = matches[2];
}
}
}
return fileName;
}
주의사항:
- 이것은, UTF-8 파일명의 값을 가져갑니다(설정되어 있는 경우).
- 다운로드 시 브라우저는 특정 문자를 대체하기 위해 이름을 변경할 수 있습니다.
"
,와 함께_
(크롬) - ascii 패턴은 따옴표로 묶인 파일 이름에 가장 적합하지만 따옴표로 묶지 않은 값을 지원합니다.이 경우 다음 텍스트가 모두 처리됩니다.
filename=
그리고 다음 날이나 다음 날 이전에;
또는 헤더 값의 끝을 파일명으로 지정합니다. - 이렇게 해도 경로 정보는 정리되지 않습니다.웹 사이트에서 파일을 저장하는 경우 브라우저의 작업이지만 노드 앱 등의 컨텍스트에서 파일을 사용하는 경우 OS별로 경로 정보를 정리하고 파일 이름만 남겨두십시오. 그렇지 않으면 시스템 파일을 덮어쓰는데 조작된 파일 이름이 사용될 수 있습니다(파일 이름).
../../../../../../../path/to/system/files/malicious.dll
)
또는 단순히:
var fileName = xhr.getResponseHeader('Content-Disposition').split("filename=")[1];
이 경우 헤더는 다음과 같습니다.
attachment; filename="test-file3.txt"
따라서 이름 있는 그룹 regexp를 사용하여 파일 이름을 쉽게 추출할 수 있었습니다.
const regExpFilename = /filename="(?<filename>.*)"/;
const filename: string | null = regExpFilename.exec(contentDispositionHeader)?.groups?.filename ?? null;
OP에는 파일명 주위에 따옴표가 없기 때문에 조금 주제에서 벗어났다는 것을 알지만, 누군가 방금 전에와 같은 패턴을 발견했을 경우에 대비하여 공유합니다.
다음 솔루션을 사용해 보십시오.
var contentDisposition = xhr.getResponseHeader('Content-Disposition');
var startIndex = contentDisposition.indexOf("filename=") + 10; // Adjust '+ 10' if filename is not the right one.
var endIndex = contentDisposition.length - 1; //Check if '- 1' is necessary
var filename = contentDisposition.substring(startIndex, endIndex);
console.log("filename: " + filename)
content-disposition이라는 작업을 수행하는 npm 패키지가 있습니다.
이게 도움이 될 거라 믿어요!
let filename = response.headers['content-disposition'].split('filename=')[1].split('.')[0];
let extension = response.headers['content-disposition'].split('.')[1].split(';')[0];
에서는, 「이러다」의 되고 있습니다.filename
문자 Unicode 문자)가되어 있습니다.-, !, (, )
)ㄹ 수 있다( ) utf-8
부호화)"부호화" 형식으로 합니다.filename*=utf-8''Na%C3%AFve%20file.txt
(자세한 내용은 여기를 참조해 주세요).이 경우 이 함수는 다음을 디코딩하는 데 사용됩니다.filename
.
const disposition = xhr.getResponseHeader('Content-Disposition');
filename = disposition.split(/;(.+)/)[1].split(/=(.+)/)[1]
if (filename.toLowerCase().startsWith("utf-8''"))
filename = decodeURIComponent(filename.replace("utf-8''", ''))
else
filename = filename.replace(/['"]/g, '')
크로스 오리진 요청을 수행하는 경우 다음 항목을 반드시 추가하십시오.Access-Control-Expose-Headers: Content-Disposition
서버측의 응답 헤더(를 참조), 헤더를 공개하기 위해서, 그 이외의 경우는,filename
자바스크립트§:
headers = {'Access-Control-Expose-Headers': 'Content-Disposition'}
return FileResponse("Naïve file.txt", filename="Naïve file.txt", headers=headers)
브라우저에서도 사용할 수 있는 라이브러리 콘텐츠 배치 첨부 파일이 있습니다.
npm i -D content-disposition-attachment
import { AxiosResponse } from "axios";
import { parse } from "content-disposition-attachment";
const getFilenameFromHeaders = ({ headers }: AxiosResponse<Blob>) => {
const defaultName = "untitled";
try {
const { attachment, filename } = parse(headers["content-disposition"]);
return attachment ? filename : defaultName;
} catch (e) {
console.error(e);
return defaultName;
}
};
멀티파트 바디를 사용하지 않는 경우 이 기능을 사용할 수 있습니다.Content-Disposition 헤더 값(string: inline; filename=filename3.png 등)에서 파일 이름을 추출하여 필요에 따라 디코딩합니다.
const getFileNameFromContentDisposition = disposition => {
if (disposition
&& (disposition.startsWith('attachment') || disposition.startsWith('inline'))
) {
let filename = disposition.startsWith('attachment')
? disposition.replace("attachment;", "")
: disposition.replace("inline;", ""); //replaces first match only
filename = filename.trim();
if (filename.includes("filename*=") && filename.includes("filename=")) {
let filenames = filename.split(";"); //we can parse by ";" because all ";"s inside filename are escaped
if (filenames.length > 1) { //"filename=" or "filename*=" not inside filename
if (filenames[0].trim().startsWith("filename*=")) { //"filename*=" is preferred
filename = filenames[0].trim();
} else {
filename = filenames[1].trim();
}
}
}
if (filename.startsWith("filename*=")) {
filename = filename.replace("filename*=", "")
.split("''").slice(1).join("''"); //remove encoding and ''
filename = decodeURIComponent(filename);
} else if (filename.startsWith("filename=")) {
filename = filename.replace("filename=", "")
if (filename.startsWith('"') && filename.endsWith('"')) {
filename = filename.slice(1, filename.length - 1); //remove quotes
}
}
return filename;
}
}
함수의 결과는 다음과 같이 이름과 확장자로 나눌 수 있습니다.
let name = getFileNameFromContentDisposition("inline; filename=demo.3.png").split(".");
let extension = name[name.length - 1];
name = name.slice(0, name.length - 1).join(".");
console.log(name); // demo.3
console.log(extension); //png
예를 들어 svg를 사용하여 섬네일을 표시할 수 있습니다.
let colors = {"png": "red", "jpg": "orange"};
//this is a simple example, you can make something more beautiful
let createSVGThumbnail = extension => `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" viewBox="0 0 18 20">
<rect x="0" y="0" width="18" height="20" fill = "#FAFEFF"/>
<rect x="0" y="7" width="18" height="6" stroke="${colors[extension] || "blue"}" fill = "${colors[extension] || "blue"}"/>
<text stroke = "white" fill = "white" font-size = "6" x = "0" y = "12.5" textLength = "18">${extension.toUpperCase()}</text>
</svg>`;
...
//You can use it as HTML element background-image
let background = "data:image/svg+xml;base64," + btoa(new TextDecoder().decode(createSVGThumbnail("png")));
언급URL : https://stackoverflow.com/questions/40939380/how-to-get-file-name-from-content-disposition
'programing' 카테고리의 다른 글
연결이 끊겼을 때 JBoss 연결 풀을 Oracle에 다시 연결할 수 있는 방법이 있습니까? (0) | 2023.03.28 |
---|---|
반응 - 부모에 대한 이벤트 트리거를 자식에서 방지 (0) | 2023.03.28 |
함수에 부모 파일이 필요할 때 하위 Wordpress 테마에서 부모 파일을 재정의하는 방법.php (0) | 2023.03.28 |
웹 API를 사용하여 익명 유형 반환 (0) | 2023.03.28 |
JSON.stringify는 일반 Javascript 배열에서 작동하지 않습니다. (0) | 2023.03.28 |