[英]How to get file name from content-disposition
I downloaded a file as response of ajax.我下载了一个文件作为 ajax 的响应。 How to get the file name and file type from
content-disposition
and display thumbnail for it.如何从
content-disposition
获取文件名和文件类型并为其显示缩略图。 I got many search results but couldn't find right way.我得到了很多搜索结果,但找不到正确的方法。
$(".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);
}
});
Console output:控制台输出:
inline; filename=demo3.png
Here is how I used it sometime back.这是我以前使用它的方式。 I'm assuming you are providing the attachment as a server response.
我假设您将附件作为服务器响应提供。
I set the response header like this from my REST service response.setHeader("Content-Disposition", "attachment;filename=XYZ.csv");
我从我的 REST 服务
response.setHeader("Content-Disposition", "attachment;filename=XYZ.csv");
设置这样的响应头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, '');
}
}
}
EDIT: Editing the answer to suit your question- use of the word inline
instead of attachment
编辑:编辑答案以适合您的问题 - 使用词
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, '');
}
}
}
This is an improvement on marjon4's answer.这是对 marjon4 答案的改进。
A much simplified way to the selected answer would be to use split like this;选择答案的一种更简单的方法是使用 split ;
var fileName = xhr.getResponseHeader('content-disposition').split('filename=')[1].split(';')[0];
Note: This solution may not work as expected if your file name itself contains a semi-colon (;)注意:如果您的文件名本身包含分号 (;),则此解决方案可能无法按预期工作
或者只是:
var fileName = xhr.getResponseHeader('Content-Disposition').split("filename=")[1];
In my case the header looks like this:在我的情况下,标题如下所示:
attachment; filename="test-file3.txt"
Therefore I was able to extract the filename pretty easily with a named group regexp:因此,我能够使用命名组正则表达式很容易地提取文件名:
const regExpFilename = /filename="(?<filename>.*)"/;
const filename: string | null = regExpFilename.exec(contentDispositionHeader)?.groups?.filename ?? null;
I know I'm slightly off topic here as OP doesn't have the quotes around the filename but still sharing in case someone comes across the same pattern as I just did我知道我在这里有点偏离主题,因为 OP 没有在文件名周围加上引号,但仍然共享以防有人遇到与我刚刚做的相同的模式
Try this solution:试试这个解决方案:
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)
有一个 npm 包可以完成这项工作: content-disposition
If you want to get the filename and support both weird url encoded UTF-8 and the ascii headers, you can use something like this如果你想获得文件名并支持奇怪的 url 编码的 UTF-8 和 ascii 头,你可以使用这样的东西
public getFileName(disposition: string): string {
const utf8FilenameRegex = /filename\*=UTF-8''([\w%\-\.]+)(?:; ?|$)/;
const asciiFilenameRegex = /filename=(["']?)(.*?[^\\])\1(?:; ?|$)/;
let fileName: string = null;
if (utf8FilenameRegex.test(disposition)) {
fileName = decodeURIComponent(utf8FilenameRegex.exec(disposition)[1]);
} else {
const matches = asciiFilenameRegex.exec(disposition);
if (matches != null && matches[2]) {
fileName = matches[2];
}
}
return fileName;
}
A couple of notes:一些注意事项:
"
, with _
(Chrome)"
,使用_
(Chrome)filename=
and before the either the next ;
filename=
和下一个;
之前的所有文本;
or the end of the header value as the file name.If you are not working with multipart body then you can use this function.如果您不使用多部分主体,则可以使用此功能。 It extracts the filename from the Content-Disposition header value (string like: inline; filename=demo3.png ) and decodes as needed.
它从 Content-Disposition 标头值(字符串如: inline; filename=demo3.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.startsWith("filename=")) {
filename = filename.replace("filename=", "");
filename = filename.slice(1, filename.length - 1); //remove quotes
} else if (filename.startsWith("filename*=")) {
filename = filename.replace("filename*=", "")
.split("''").slice(1).join("''"); //remove encoding and ''
filename = decodeURIComponent(filename);
}
return filename;
}
}
The result of the function can be split into name and extension as follows:函数的结果可以拆分为名称和扩展名,如下所示:
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
You can display thumbnail, for example, using svg:例如,您可以使用 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")));
(file gets saved in binary format in the browser. the filename is in client's Network/header/Content-Disposition, we need to fetch the filename) (文件在浏览器中以二进制格式保存。文件名在客户端的 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'
});
}
Didn't find any response on stackoverflow in my case. 在我的情况下没有在stackoverflow上找到任何响应。 I receive a content-disposition like that: inline;
我收到了这样的内容处理: 内联; filename*=UTF-8''Dossier%20de%20diagnostic%20technique.pdf
文件名* = UTF-8''Dossier%20de%20diagnostic%20technique.pdf
I modified the regex to deal with an UTF-8 string if present : var regex = /filename[^;=\\n] =(UTF-8(['"] ))?(.*)/; 我修改了正则表达式来处理UTF-8字符串(如果存在): var regex = / filename [^; = \\ n] =(UTF-8(['“] ))?(。*)/;
And here is my function : 这是我的功能:
function getFileNameByContentDisposition(contentDisposition){
var regex = /filename[^;=\n]*=(UTF-8(['"]*))?(.*)/;
var matches = regex.exec(contentDisposition);
var filename;
if (matches != null && matches[3]) {
filename = matches[3].replace(/['"]/g, '');
}
return decodeURI(filename);
}
EDIT : I didn't test it that much. 编辑:我没有那么多测试。 Don't forget to wrap it with a try / catch in a NodeJS code.
不要忘记在NodeJS代码中使用try / catch包装它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.