发布时间:2023-04-22 文章分类:WEB开发, 电脑百科 投稿人:赵颖 字号: 默认 | | 超大 打印

流文件乱码问题解决方案

    • 问题介绍:
    • 一、前端方式解决:
  • 二、后端方式解决:
    • 三、文件预览实现
    • 四、点击按钮打开新窗口预览

问题介绍:

打开或者预览全是乱码。预览pdf如下图:
Vue 采用blob下载后端返回的pdf流或者excel流文件乱码问题解决方案
解决办法:

1. 后端接口返回的blob文件流,你下载下来的文件是乱码的?

解决办法 :让你的后端设置流的编码为utf-8。请跟后端大佬说,一定要给blob格式的文件流。

2. 后端返回的blob文件流,并且已经设置了utf-8,但是你接受的接口返回值,依然是乱码?

解决办法: 肯定没有设置 responseType: “arraybuffer”。

一、前端方式解决:

预览pdf如下图:
Vue 采用blob下载后端返回的pdf流或者excel流文件乱码问题解决方案

这个charset=utf-8一定要添加,不添加可能乱码,如果后台返回的格式里面有,那就没必要了!
代码:
const binaryData = []
binaryData.push(res.data)
// 获取blob链接
this.pdfUrl = window.URL.createObjectURL(new Blob(binaryData, { type: ‘application/pdf;charset=utf-8’ }))
window.open(this.pdfUrl)

pdf下载如下图:
Vue 采用blob下载后端返回的pdf流或者excel流文件乱码问题解决方案

代码如下:
this.pdfUrl = window.URL.createObjectURL(new Blob([res.data], { type: application/pdf;charset=utf-8 }))
const fname = 合同 // 下载文件的名字
const link = document.createElement(‘a’)
console.log(this.pdfUrl)
link.href = this.pdfUrl
link.setAttribute(‘download’, fname)
document.body.appendChild(link)
link.click()
代码:
export default {
  name: 'pdf',
  async mounted () {
    this.pdfHeight = '100%'
    this.ewpId = this.$route.query.ewpId
    this.pdfUrl = await this.getPdf(this.baseUrl + '/rcgl/TalPolicy/onlinePreview?id=' + this.ewpId + '&BDSOFT-TOKEN=' + this.userToken)
  },
  data () {
    return {
      baseUrl: process.env.VUE_APP_BASE_API,
      pdfUrl: '',
      ewpId: '',
      pdfHeight: 0
    }
  },
  methods: {
    async getPdf (url) {
      // eslint-disable-next-line no-undef
      const data = await axios.get(url, {
        responseType: 'arraybuffer'
      })
      const blob = new Blob([data.data], { type: 'application/pdf' })
      return URL.createObjectURL(blob)
    }
  },
  computed: {
    ...mapState('global', {
      userToken: state => state.token,
      unitId: state => state.userInfo.b00
    })
  }
}

二、后端方式解决:

因为有的文件可能含有中文,因此在文件传输过程中会涉及到编码问题。后台的代码需要将输出流的编码格式设置为UTF-8。

response.setContentType("application/octet-stream;charset=UTF-8");

另一种方式就是:(优先级最高)

response.setCharacterEncoding("UTF-8"); // 设置文件流编码格式 不然中文会乱码

这样前端接收到输出流的时候是以Blob类型接收的。

代码:
 @Override
    public void onlinePreview(String filePath, HttpServletResponse response) throws Exception {
        //获取文件类型
        String[] str = filePath.split("\\.");
        if (str.length == 0) {
            throw new Exception("文件格式不正确");
        }
        String suffix = str[str.length - 1];
        if (!suffix.equals("txt") && !suffix.equals("doc") && !suffix.equals("docx") && !suffix.equals("xls")
                && !suffix.equals("xlsx") && !suffix.equals("ppt") && !suffix.equals("pptx")) {
            throw new Exception("文件格式不支持预览");
        }
        InputStream in = FileConvertUtil.convertLocaleFile(filePath, suffix);
        response.setContentType("application/octet-stream;charset=UTF-8");
        OutputStream outputStream = response.getOutputStream();
        //创建存放文件内容的数组
        byte[] buff = new byte[1024];
        //所读取的内容使用n来接收
        int n;
        //当没有读取完时,继续读取,循环
        while ((n = in.read(buff)) != -1) {
            //将字节数组的数据全部写入到输出流中
            outputStream.write(buff, 0, n);
        }
        //强制将缓存区的数据进行输出
        outputStream.flush();
        //关流
        outputStream.close();
        in.close();
    }

三、文件预览实现

controller 代码

@ApiOperation(value = "系统文件在线预览", notes = "系统文件在线预览")
    @GetMapping(Urls.TalPolicy.onlinePreview)
    public void onlinePreview(String id, HttpServletResponse  response) throws Exception {
        Assert.notNull(id, "用户id不能为空");
        TalPolicy Policy = TalPolicyService.getAllById(id);
        if (Policy != null) {
            String fid = Policy.getFileid();
            if (!StringUtils.isEmpty(fid)) {
                SAttachmentFile sAttachmentFile = fileManagerService.getById(fid);
                String filePath = sAttachmentFile.getFilepath();
                TalPolicyService.onlinePreview(filePath, response);
            }
        }
    }

service 代码

void onlinePreview(String filePath, HttpServletResponse  response) throws Exception;

serviceimpl代码

 @Override
    public void onlinePreview(String filePath, HttpServletResponse response) throws Exception {
        //获取文件类型
        String[] str = filePath.split("\\.");
        if (str.length == 0) {
            throw new Exception("文件格式不正确");
        }
        String suffix = str[str.length - 1];
        if (!suffix.equals("txt") && !suffix.equals("doc") && !suffix.equals("docx") && !suffix.equals("xls")
                && !suffix.equals("xlsx") && !suffix.equals("ppt") && !suffix.equals("pptx")) {
            throw new Exception("文件格式不支持预览");
        }
        InputStream in = FileConvertUtil.convertLocaleFile(filePath, suffix);
        response.setContentType("application/octet-stream;charset=UTF-8");
        OutputStream outputStream = response.getOutputStream();
        //创建存放文件内容的数组
        byte[] buff = new byte[1024];
        //所读取的内容使用n来接收
        int n;
        //当没有读取完时,继续读取,循环
        while ((n = in.read(buff)) != -1) {
            //将字节数组的数据全部写入到输出流中
            outputStream.write(buff, 0, n);
        }
        //强制将缓存区的数据进行输出
        outputStream.flush();
        //关流
        outputStream.close();
        in.close();
    }

工具类及其他详情步骤参考:
java用openOffice实现在线预览

四、点击按钮打开新窗口预览

 <el-table-column
          label="操作"
          align="center"
          width="120px">
          <template slot-scope="scope">
            <div style="line-height: 1; font-size: 0;">
              <el-button size="mini" @click="prewelRow(scope.row)">查看</el-button>
            </div>
          </template>
        </el-table-column>
data () {
    return {
      baseUrl: process.env.VUE_APP_BASE_API
      }
      },
computed: {
    ...mapState('global', {
      userToken: state => state.token,
      unitId: state => state.userInfo.b00
    })
  }
methods: {
 prewelRow: async function (row) {
      const pdfUrl = await this.getPdf(this.baseUrl + '/rcgl/TalPolicy/onlinePreview?id=' + row.recordid + '&TOKEN=' +   	   		this.userToken)
      window.open(pdfUrl)
    },
}