下载后在客户端获取文件名。 CORS
Get file name at client side after downloading. CORS
我已经成功地从服务器端下载了一个文件:
[EnableCors("AllowAll")]
[HttpGet("{id}", Name = "Get")]
public IActionResult Get(int id)
{
var fileName = "Far30b4949.x86.20170503.zip"; //*** Creation file name
var filepath = _hostingEnvironment.WebRootPath;
byte[] fileBytes = System.IO.File.ReadAllBytes(_hostingEnvironment.WebRootPath +
@"\" + fileName);
return File(fileBytes, "application/zip", fileName); //*** Sending file name
}
客户端代码:
public downloadFile() {
let projectAUrl = 'http://localhost:49591/api/file/5';
return this.http.get(projectAUrl, {responseType: ResponseContentType.Blob})
.map((response) => {
return new Blob([response.blob()], {type:'application/zip'})
})
.subscribe((res)=> {
saveAs(res, "Name does not come here")//there is no file name,
//but there is a file type("application/zip")
});
}
CORS 设置:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
//Add CORS support to the service
services.AddCors(options=> options.AddPolicy("AllowAll", p =>
p.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()));
}
我在客户端有什么:
但是,从服务器端下载文件时,客户端没有文件名。如何获取文件名?
更新:
我删除了对 map()
的调用:
public downloadFile() {
let projectAUrl = 'http://localhost:49591/api/file/5';
return this.http.get(projectAUrl, {responseType: ResponseContentType.Blob})
.subscribe((res)=> {
saveAs(res, "Name does not come here")//there is no file name,
//but there is a file type("application/zip")
});
}
但是没有文件名:
更新二:
如果我对 CORS 使用以下策略:
services.AddCors(options => options.AddPolicy("ExposeResponseHeaders",
p =>
{
p.WithOrigins("http://localhost:49591")
.WithExposedHeaders("Content-Disposition");
}));
然后我得到以下错误:
XMLHttpRequest cannot load http://localhost:49591/api/file/5. No 'Access-
Control-Allow-Origin' header is present on the requested resource. Origin
'http://localhost:3000' is therefore not allowed access. The response had
HTTP status code 500.
只需删除对 map
的调用并在 subscribe
lambda 函数中提取 blob 数据和文件名:
public downloadFile() {
let projectAUrl = 'http://localhost:49591/api/file/5';
return this.http.get(projectAUrl, {responseType: ResponseContentType.Blob})
.subscribe((response)=> {
var blob = new Blob([response.blob()], {type:'application/zip'});
var header = response.headers.get('Content-Disposition');
var filenameRegex = /filename[^;=\n]*=((['"]).*?|[^;\n]*)/;
var matches = filenameRegex.exec(header);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
saveAs(blob, fileName);
});
}
Content-Disposition
header 解析取自:
How to get file name from content-disposition
关于您的 CORS 配置
您可以尝试使用以下策略(添加您可能发现浏览器无法读取的任何其他 header):
services.AddCors(options => options.AddPolicy("ExposeResponseHeaders",
p =>
{
p.WithOrigins("http://localhost:3000") // single origin THIS MUST BE THE SAME OF YOUR ANGULAR APPLICATION (not your ASP.NET Core app address)
.AllowAnyMethod() // any method
.AllowAnyHeader() // any header is *allowed*
.AllowCredentials() // credentials allowed
.WithExposedHeaders("Content-Disposition"); // content-disposition is *exposed* (and allowed because of AllowAnyHeader)
}));
尝试在 return 结果之前在 Controller 中显式添加 "Access-Control-Expose-Headers"。
例如:
[HttpPost("export/excel")]
public async Task<IActionResult> ExportToExcel([FromBody] ExportReportRequest request)
{
...
(byte[] fileContents, string fileName) = await this.salaryService.ExportReportToExcelAsync(request, userId).ConfigureAwait(false);
this.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
return this.File(fileContents, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}
我已经成功地从服务器端下载了一个文件:
[EnableCors("AllowAll")]
[HttpGet("{id}", Name = "Get")]
public IActionResult Get(int id)
{
var fileName = "Far30b4949.x86.20170503.zip"; //*** Creation file name
var filepath = _hostingEnvironment.WebRootPath;
byte[] fileBytes = System.IO.File.ReadAllBytes(_hostingEnvironment.WebRootPath +
@"\" + fileName);
return File(fileBytes, "application/zip", fileName); //*** Sending file name
}
客户端代码:
public downloadFile() {
let projectAUrl = 'http://localhost:49591/api/file/5';
return this.http.get(projectAUrl, {responseType: ResponseContentType.Blob})
.map((response) => {
return new Blob([response.blob()], {type:'application/zip'})
})
.subscribe((res)=> {
saveAs(res, "Name does not come here")//there is no file name,
//but there is a file type("application/zip")
});
}
CORS 设置:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
//Add CORS support to the service
services.AddCors(options=> options.AddPolicy("AllowAll", p =>
p.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()));
}
我在客户端有什么:
但是,从服务器端下载文件时,客户端没有文件名。如何获取文件名?
更新:
我删除了对 map()
的调用:
public downloadFile() {
let projectAUrl = 'http://localhost:49591/api/file/5';
return this.http.get(projectAUrl, {responseType: ResponseContentType.Blob})
.subscribe((res)=> {
saveAs(res, "Name does not come here")//there is no file name,
//but there is a file type("application/zip")
});
}
但是没有文件名:
更新二:
如果我对 CORS 使用以下策略:
services.AddCors(options => options.AddPolicy("ExposeResponseHeaders",
p =>
{
p.WithOrigins("http://localhost:49591")
.WithExposedHeaders("Content-Disposition");
}));
然后我得到以下错误:
XMLHttpRequest cannot load http://localhost:49591/api/file/5. No 'Access-
Control-Allow-Origin' header is present on the requested resource. Origin
'http://localhost:3000' is therefore not allowed access. The response had
HTTP status code 500.
只需删除对 map
的调用并在 subscribe
lambda 函数中提取 blob 数据和文件名:
public downloadFile() {
let projectAUrl = 'http://localhost:49591/api/file/5';
return this.http.get(projectAUrl, {responseType: ResponseContentType.Blob})
.subscribe((response)=> {
var blob = new Blob([response.blob()], {type:'application/zip'});
var header = response.headers.get('Content-Disposition');
var filenameRegex = /filename[^;=\n]*=((['"]).*?|[^;\n]*)/;
var matches = filenameRegex.exec(header);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
saveAs(blob, fileName);
});
}
Content-Disposition
header 解析取自:
How to get file name from content-disposition
关于您的 CORS 配置
您可以尝试使用以下策略(添加您可能发现浏览器无法读取的任何其他 header):
services.AddCors(options => options.AddPolicy("ExposeResponseHeaders",
p =>
{
p.WithOrigins("http://localhost:3000") // single origin THIS MUST BE THE SAME OF YOUR ANGULAR APPLICATION (not your ASP.NET Core app address)
.AllowAnyMethod() // any method
.AllowAnyHeader() // any header is *allowed*
.AllowCredentials() // credentials allowed
.WithExposedHeaders("Content-Disposition"); // content-disposition is *exposed* (and allowed because of AllowAnyHeader)
}));
尝试在 return 结果之前在 Controller 中显式添加 "Access-Control-Expose-Headers"。
例如:
[HttpPost("export/excel")]
public async Task<IActionResult> ExportToExcel([FromBody] ExportReportRequest request)
{
...
(byte[] fileContents, string fileName) = await this.salaryService.ExportReportToExcelAsync(request, userId).ConfigureAwait(false);
this.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
return this.File(fileContents, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}