将后端resources中的文件返给前端下载的方法

//后端

java 复制代码
@GetMapping("getmoban")
// 下载模板
    public AppResult<String> getmoban(HttpServletResponse response) {
        // 尝试-with-resources确保流会被自动关闭
        try (InputStream resourceAsStream = this.getClass().getResourceAsStream("/excelTemplates/importQualificationAbilityExcel.xlsx");
             ServletOutputStream out = response.getOutputStream()) {

            if (resourceAsStream == null) {
                return AppResultBuilder.error(500, "模板文件不存在");
            }

            // 设置响应头信息
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment; filename=\"" +
                    URLEncoder.encode("导入excel模板.xlsx", "UTF-8") + "\"");
            // 有些浏览器需要此头信息
            response.setHeader("filename", URLEncoder.encode("导入excel模板.xlsx", "UTF-8"));

            byte[] buffer = new byte[1024];
            int len;
            while ((len = resourceAsStream.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            out.flush(); // 确保所有数据都被写出

            return AppResultBuilder.success("下载成功.");

        } catch (UnsupportedEncodingException e) {
            return AppResultBuilder.error(500, "编码错误: " + e.getMessage());
        } catch (IOException e) {
            return AppResultBuilder.error(500, "文件读写错误: " + e.getMessage());
        }
    }

前端

html 复制代码
/**
 * 二进制文件下载工具(优化版)
 * @param binFile 二进制文件流(Blob对象)
 * @param fileName 保存的文件名
 * @param blobType MIME类型,默认为excel类型
 */
export const downloadBinaryFile = (
  binFile: Blob,
  fileName: string,
  blobType = 'application/vnd.ms-excel',
) => {
  // 确保传入的是Blob对象,避免类型错误
  if (!(binFile instanceof Blob)) {
    console.error('无效的二进制文件流')
    return
  }

  // 创建URL对象
  const url = window.URL.createObjectURL(new Blob([binFile], { type: blobType }))
  const a = document.createElement('a')
  a.href = url
  a.download = fileName // 设置文件名(支持中文)

  // 触发下载
  document.body.appendChild(a)
  a.click()

  // 清理资源
  document.body.removeChild(a)
  window.URL.revokeObjectURL(url) // 释放URL对象,避免内存泄漏
}
html 复制代码
import { downloadBinaryFile } from '@/utils/helpUtils.ts'

/**
 * 下载模板文件(修改后的版本)
 * @returns 无返回值,直接触发浏览器下载
 */
export const downloadimportFile = async () => {
  try {
    // 关键:设置responseType为blob,告知axios接收二进制流
    const result: AxiosResponse<Blob> = await axios({
      method: 'get',
      url: '/api/job/qualification/getmoban',
      responseType: 'blob', // 必须设置,否则会解析为JSON导致乱码
      timeout: 60000, // 加大超时时间,避免大文件下载超时
    })

    // 从响应头获取文件名(后端设置的filename)
    const contentDisposition = result.headers['content-disposition'] || ''
    let fileName = '' // 默认文件名

    // 解析响应头中的文件名(处理编码问题)
    if (contentDisposition) {
      const match = contentDisposition.match(/filename="(.*?)"/)
      if (match && match[1]) {
        fileName = decodeURIComponent(match[1]) // 解码URLEncoded的文件名
      }
    }
    // 调用下载工具方法处理二进制流
    downloadBinaryFile(result.data, fileName)
    return { success: true } // 返回成功状态给调用方
  } catch (error: any) {
    if (isCustomAxiosError(error)) {
      console.error('文件下载失败:', error.message)
    } else {
      console.error('文件下载异常:', error)
    }
    return { success: false, msg: '文件下载失败' }
  }
}
相关推荐
阿虎儿28 分钟前
React Context 详解:从入门到性能优化
前端·vue.js·react.js
Sailing1 小时前
🚀 别再乱写 16px 了!CSS 单位体系已经进入“计算时代”,真正的响应式布局
前端·css·面试
喝水的长颈鹿1 小时前
【大白话前端 03】Web 标准与最佳实践
前端
爱泡脚的鸡腿1 小时前
Node.js 拓展
前端·后端
左夕2 小时前
分不清apply,bind,call?看这篇文章就够了
前端·javascript
Zha0Zhun3 小时前
一个使用ViewBinding封装的Dialog
前端
兆子龙3 小时前
从微信小程序 data-id 到 React 列表性能优化:少用闭包,多用 data-*
前端
滕青山3 小时前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js
时光不负努力3 小时前
编程常用模式集合
前端·javascript·typescript
恋猫de小郭3 小时前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios