前端下载文件后,文件损坏,无法打开?

环境说明vue axios + java springboot

我们在开发项目经常遇到的需求是 文件上传下载,这篇文章将重点介绍 文件下载遇到的各种问题以及解决方案

1.在前端请求中参数 responseType 是指 期望的响应类型,决定了如何处理服务器返回的数据,常见的有 arraybuffer,blob,stream

2.接受到后端返回的数据后,定义的type: contentType

const blob = new Blob([response.data],{ type: contentType });

对应后端 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

常见的值有 application/octet-stream,application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 等,如果不定义或者前后端定义不一致都会导致前端能接受到文件,但是打开文件时报错文件损坏

3.还有有时候会碰到跨域问题,跨域设定完毕后一定要刷新页面(即使修改的后端),很多时候明明设定都调整好了,页面就是报错,很可能就是没有刷新页面导致的

附上代码

复制代码
export function httpDownFile({ httpUrl, httpParams,httpResponseType}) {
    if(!httpResponseType){
        httpResponseType = 'blob'
    }
    axios({
        method: 'get',
        url: httpUrl,
        params:httpParams,
        responseType: httpResponseType
    }).then(function (response) {
        console.log("文件下载成功");
        //获取后端返回的数据类型
        const contentType = response.headers['content-type'];
        // 从Content-Disposition头中提取文件名
        const contentDisposition = response.headers['content-disposition'];
        const filenameMatch = contentDisposition.match(/filename\*=UTF-8''(.*)/);
        const filename = decodeURIComponent(filenameMatch[1]);
        const blob = new Blob([response.data],{ type: contentType });
        const downloadUrl = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.download = filename;
        document.body.appendChild(link);
        link.click();
        window.URL.revokeObjectURL(downloadUrl);
    }).catch(function (error) {
        console.log(error);
    });
}

调用

复制代码
  httpDownFile({
    httpUrl:'/file/excel',
    httpParams:{
      "name":'aaa'
    },
    httpResponseType:'blob'
  })

后端

复制代码
    @GetMapping("/file/excel")
    public ResponseEntity<byte[]> selectSql1(@RequestParam String name) {
        try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            // 创建工作表和数据
            Sheet sheet = workbook.createSheet("示例数据");
            Row row = sheet.createRow(0);
            row.createCell(0).setCellValue("编号");
            row.createCell(1).setCellValue("姓名");
            row.createCell(2).setCellValue("自定义参数");

            // 添加示例数据
            Row dataRow = sheet.createRow(1);
            dataRow.createCell(0).setCellValue(1);
            dataRow.createCell(1).setCellValue("张三");
            dataRow.createCell(2).setCellValue(name); // 使用请求参数填充数据

            // 写入数据到流
            workbook.write(outputStream);

            // 构造响应
            byte[] excelData = outputStream.toByteArray();
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", "example.xlsx");
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(excelData);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(500).body(null);
        }
    }

好了,你还遇到过哪些离谱的问题,留言给我吧

相关推荐
玲小珑14 小时前
LangChain.js 完全开发手册(十九)前端 AI 开发进阶技巧
前端·langchain·ai编程
哆啦A梦158814 小时前
46 修改购物车数据
前端·vue.js·node.js
程序员ys14 小时前
Vue的响应式系统是怎么实现的
前端·javascript·vue.js
Sailing14 小时前
🔥 React 高频 useEffect 导致页面崩溃的真实案例:从根因排查到彻底优化
前端·react.js·面试
aduzhe14 小时前
关于在嵌入式中打印float类型遇到的bug
前端·javascript·bug
Sailing14 小时前
🔥 大模型时代最讽刺的职业出现了:“大模型善后工程师”
前端·openai·ai编程
o***Z44814 小时前
前端组件表单验证,React Hook Form与VeeValidate
前端·react.js·前端框架
xiaoxue..14 小时前
Vibe Coding之道:从Hulk扩展程序看Prompt工程的艺术
前端·人工智能·prompt·aigc
程序猿小蒜14 小时前
基于springboot的汽车资讯网站开发与实现
java·前端·spring boot·后端·spring
q***985214 小时前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端