javascript - 为什么 URL.createObjectURL 开始将我的文件名作为 GUID?
问题描述
这工作得很好,突然之间就不行了。相关文件的历史显示没有明显的变化会导致它。我没有得到真实的文件名,比如“upload.txt”,而是得到一个没有扩展名的 GUID。因此浏览器永远无法打开文件,系统在下载而不是打开时也无法打开。
它正在正确发送文件名:
服务器端:
[HttpGet("download/{fileId}")]
public async Task<IActionResult> DownloadFile(int fileId)
{
var file = await _fileRepository.GetByIdAsync(fileId).ConfigureAwait(true);
if (file == null)
return NotFound();
var path = _fileService.GetUploadedFilePath(file.FileNameInStorage);
if (!System.IO.File.Exists(path))
return NotFound();
var memory = await PopulateMemoryStream(path).ConfigureAwait(true);
memory.Position = 0;
var contentType = FileUtils.GetContentTypeByExtension(file.Extension);
var displayName = file.OriginalFileName;
if (!Path.HasExtension(displayName))
displayName += file.Extension;
System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
FileName = displayName,
Inline = true // false = prompt the user for downloading; true = browser to try to show the file inline
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("X-Content-Type-Options", "nosniff");
return File(memory, contentType, displayName);
}
客户端:
downloadFile(fileId: number): void {
this.fileService.transmitFile(fileId).subscribe(res => {
const fileURL = URL.createObjectURL(res);
window.open(fileURL, '_blank');
});
}
transmitFile(fileId: number): any {
return this.http.get(`${this.apiUrl}/file/download/${fileId}`, { headers: { 'Accept': 'application/octet-stream' }, observe: 'response', responseType: 'arraybuffer' })
.pipe(
map((res) => {
return new Blob([res.body], { type: res.headers.get('content-type') });
})
);
}
解决方案
以下是我如何更改前端以允许使用扩展下载。不幸的是,这些文件仍然会获得文件名的 GUID,但是当下载或在浏览器中正确打开时,它们确实会附带扩展名。您只需要确保设置正确的内容类型。
downloadFile(fileId: number): Observable<HttpResponse<ArrayBuffer>> {
return this.http.get(`${this.apiUrl}/file/download/${fileId}`, { headers: { 'Accept': 'application/octet-stream' }, observe: 'response', responseType: 'arraybuffer'
});
}
downloadFile(fileId: number): void {
this.fileService.downloadFile(fileId).subscribe(res => {
const blob = new Blob([res.body], { type: res.headers.get('content-type') });
const file = new File([blob], this.resume.originalFileName, { type: res.headers.get('content-type') });
const fileURL = URL.createObjectURL(file);
window.open(fileURL, '_blank');
});
}
奖励:这是设置内容类型的服务器端代码。大多数情况已经过测试。
public static string GetContentTypeByExtension(string ext)
{
switch (ext)
{
case ".png":
return "image/png";
case ".jpg":
case ".jpeg":
return "image/jpeg";
case ".pdf":
return "application/pdf";
case ".doc":
case ".dot":
case ".rtf":
return "application/msword";
case ".docx":
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
case ".docm":
case ".dotm":
return "application/vnd.ms-word.document.macroEnabled.12";
case ".tif":
case ".tiff":
return "image/tiff";
case ".txt":
return "text/plain";
case ".xls":
case ".xlt":
return "application/vnd.ms-excel";
case ".xlsx":
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
case ".xltx":
return "application/vnd.openxmlformats-officedocument.spreadsheetml.template";
case ".xlsm":
return "application/vnd.ms-excel.sheet.macroEnabled.12";
case ".xltm":
return "application/vnd.ms-excel.template.macroEnabled.12";
default:
return "application/octet-stream";
}
}
推荐阅读
- google-cloud-platform - 当自定义日志消息传送到 GCP Stackdriver 时发送通知
- javascript - 如何通过表单提交保持 Chrome 扩展在页面重新加载时运行?
- r - 闪亮的 fileInput() 对多个文件选择没有反应
- android - Android导航组件:以编程方式从与家不同的目的地开始?
- vba - 是否需要 VBA 才能根据组合框中的名称运行 SQL 查询?
- sql - 在同一个表的两列中查找值相同的数据
- amazon-web-services - 如何将 Spring Cloud Function 连续部署到 AWS lambda
- javascript - 如何使用 getusermedia 从多个后置摄像头检测主/长焦摄像头
- java - 如何从另一个控制器操作 TableView?
- node.js - 运行 vue-cli-service serve 时来自 Node.js 的高 CPU 使用率