流文件乱码问题解决方案
-
- 问题介绍:
- 一、前端方式解决:
- 二、后端方式解决:
-
- 三、文件预览实现
- 四、点击按钮打开新窗口预览
问题介绍:
打开或者预览全是乱码。预览pdf如下图:
解决办法:
1. 后端接口返回的blob文件流,你下载下来的文件是乱码的?
解决办法 :让你的后端设置流的编码为utf-8。请跟后端大佬说,一定要给blob格式的文件流。
2. 后端返回的blob文件流,并且已经设置了utf-8,但是你接受的接口返回值,依然是乱码?
解决办法: 肯定没有设置 responseType: “arraybuffer”。
一、前端方式解决:
预览pdf如下图:
这个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下载如下图:
代码如下:
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)
},
}