在我的javascript客户端中,我使用fetch来调用服务器来检索服务器生成的文件。我使用以下客户端代码:
var _url = "";
var initParms = {
method: "GET",
mode: 'cors'
}
fetch(_url, initParms)
.then(response => {
if(response.ok){
alert(response.headers.get("content-disposition"));
return response.blob();
}
throw new Error("Network response was not OK.");
})
.then(blob => {
var url = new URL.createObjectURL(blob);
})
这实际上很好用。但是,服务器会为文件生成文件名,并将其作为content-disposition标头的一部分包含在响应中。
我需要使用服务器生成的文件名将此文件保存到用户的计算机。在Postman中,我实际上可以看到响应的内容处置标头设置为:Content-Disposition: attachment;filename=myfilename.txt
。
我尝试从响应中读取内容处理(请参阅我的js代码中的警告),但我总是得到null(即使相同的响应显示Postman中的内容处置)。
我做错了吗?有没有办法使用fetch响应检索文件名?有没有更好的方法从服务器获取文件名和文件?
P.S。这是我返回文件的服务器端代码:
控制器操作
public IHttpActionResult GetFile(){
return new FileResult("myfilename.txt","Hello World!");
}
FileResult Class
public class FileResult : IHttpActionResult
{
private string _fileText = "";
private string _fileName = "";
private string _contentType = "";
public FileResult(string name, string text)
{
_fileText = text;
_fileName = name;
_contentType = "text/plain";
}
public Task<HttpResponseMessage> ExecuteActionAsync(CancellationToken token)
{
Stream _stream = null;
if (_contentType == "text/plain")
{
var bytes = Encoding.Unicode.GetBytes(_fileText);
_stream = new MemoryStream(bytes);
}
return Task.Run(() =>
{
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(_stream),
};
response.Content.Headers.ContentType =
new MediaTypeHeaderValue(_contentType);
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = _fileName
};
return response;
}, token);
修改
我的问题是关于抓取而不是ajax api。此外,在我的代码中,我表明我已经从响应中读取标题,就像在建议的答案中显示的接受答案一样。但是,正如我的帖子所述,此解决方案不适用于fetch。
答案 0 :(得分:1)
因此,在发布此问题后不久,我遇到了this issue on Github。它显然与使用CORS有关。
建议的解决方法是将Access-Control-Expose-Headers:Content-Disposition
添加到服务器上的响应标头中。
这很有用!
答案 1 :(得分:1)
您可以像这样从 content-disposition 标头中提取文件名:
let filename = '';
fetch(`/url`, { headers: { Authorization: `Bearer ${token}` }}).then((res) => {
const header = res.headers.get('Content-Disposition');
const parts = header!.split(';');
filename = parts[1].split('=')[1];
return res.blob();
}).then((blob) => {
// Use `filename` here e.g. with file-saver:
// saveAs(blob, filename);
});