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

环境说明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);
        }
    }

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

相关推荐
就叫飞六吧3 小时前
基于spring web实现简单分片上传demo
java·前端·spring
AAA阿giao3 小时前
拼乐高式开发:深入剖析 React 组件通信、弹窗设计与样式管理
开发语言·前端·javascript·react.js·前端框架·props·components
lvbinemail3 小时前
svn的web管理后台服务svnWebUI
运维·前端·svn·jar
Violet_YSWY3 小时前
Promise 讲解
前端
软件开发技术深度爱好者3 小时前
数学公式生成器HTML版
前端·html
Marshmallowc4 小时前
CSS 布局原理:为何“负边距”是栅格系统的基石?
前端·css·面试
Rysxt_4 小时前
Vue 3 项目核心:App.vue 文件的作用与配置详解
前端·javascript·vue.js
洛阳纸贵4 小时前
JAVA高级工程师--Maven父子关系专题
java·前端·maven
imkaifan4 小时前
10、vue3中针对图片的处理
前端·javascript·vue.js
柯南二号4 小时前
【大前端】【iOS】iOS 使用 Objective-C 绘制几大常见布局(UIKit / Core Graphics 实战)
前端·ios