首页 > 解决方案 > 为什么 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') });
  })
);

}

标签: javascriptc#angulartypescript

解决方案


以下是我如何更改前端以允许使用扩展下载。不幸的是,这些文件仍然会获得文件名的 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";
        }
    }

推荐阅读