You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Angular下载阿拉伯文件名被替换为下划线问题求助

问题描述

本地开发基于Spring Boot与Angular 14的文件上传下载项目,出现以下异常:

  • 含阿拉伯字符的文件上传后可正常存储至本地,但下载时文件名中的阿拉伯字符会被替换为下划线。
  • 若移除Content-Disposition头中的文件名参数,文件能以阿拉伯原文件名下载,但除.doc格式外,.txt、.jpg、.png等文件的扩展名会被自动改为.htm。

前端代码

<div class="card mt-3">
  <div class="card-header">لائحة المرفقات</div>
  <ul
    class="list-group list-group-flush"
    *ngFor="let file of fileInfos | async">
    <li class="list-group-item">
      <a href="{{ file.url }}" target="_blank" download="{{ file.name }}">{{ file.name }}</a>
    </li>
  </ul>
</div>

后端原代码

@GetMapping("/files/{fileRef}/{filename}")
public ResponseEntity<Resource> getFile( @PathVariable String filename,@PathVariable String fileRef) {

  Resource file = storageService.load(fileRef+'/'+filename);
  
  return ResponseEntity.ok()
      .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file);
}

已尝试无效的方法

  • 强制设置Content-Type为application/x-www-form-urlencoded; charset=utf-8
  • 使用new String(file.getFilename().getBytes(),Charset.forName("UTF-8"))重新编码文件名

解决方法

核心问题是HTTP响应头Content-Disposition中的非ASCII字符未按标准编码,导致浏览器解析失败;同时错误的Content-Type设置引发扩展名异常。

后端修正:使用标准编码处理文件名

Spring 5及以上版本提供的ContentDisposition类可自动生成兼容RFC 5987的编码格式,同时适配不同浏览器的解析规则:

@GetMapping("/files/{fileRef}/{filename}")
public ResponseEntity<Resource> getFile(@PathVariable String filename, @PathVariable String fileRef) {
    Resource file = storageService.load(fileRef + '/' + filename);
    String originalFilename = file.getFilename();

    // 构建符合标准的Content-Disposition头
    ContentDisposition contentDisposition = ContentDisposition.builder("attachment")
            .filename(originalFilename, StandardCharsets.UTF_8)
            .build();

    // 自动识别文件MIME类型,避免扩展名被篡改
    MediaType mediaType = MediaTypeFactory.getMediaType(file)
            .orElse(MediaType.APPLICATION_OCTET_STREAM);

    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
            .contentType(mediaType)
            .body(file);
}

关键细节:

  1. ContentDisposition的作用:自动生成filename(兼容旧浏览器)和filename*=UTF-8''编码后的文件名两个参数,确保阿拉伯字符能被正确解析。
  2. 正确设置Content-Type:通过MediaTypeFactory根据文件自动匹配MIME类型,避免浏览器因无法识别类型而修改扩展名。

前端优化(可选)

使用Angular属性绑定替代插值表达式,减少编码风险:

<li class="list-group-item">
  <a [href]="file.url" target="_blank" [download]="file.name">{{ file.name }}</a>
</li>

内容的提问来源于stack exchange,提问作者hamzaP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:31:02