springboot后端返回图片,vue前端接收并显示的解决方案
controller层service层。
·
后端图片数据返回
后端通过二进制流的形式,写入response中
controller层
/**
* 获取签到二维码
*/
@GetMapping("/sign-up-pict")
public void signUpPict(Long id, Long semId, HttpServletResponse response) throws NoSuchAlgorithmException {
signUpService.getImage(id, semId, response);
}
service层
/**
* 返回二维码
*
* @param id 教师id
* @param semId 课程id
* @param response
* @return
*/
@Override
public void getImage(Long id, Long semId, HttpServletResponse response) throws NoSuchAlgorithmException {
// 保存生成的二维码图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 业务逻辑, 全部忽略删除了...
// 设置返回数据类型
response.setContentType("image/png");
try {
// 将图片数据写入out中
OutputStream out = response.getOutputStream();
// 将图片数据写入out中, 返回前端
ImageIO.write(image, "png", out);
out.close();
}catch (IOException e) {
throw new RRException(ErrorCode.IMAGE_GENERATE_FAILED);
}
}
前端axios接受数据
axios接受数据时,responseType 默认返回数据类型是 json,必须将其改为返回数据类型 blob。否则axois无法正确解析数据。
这里的http.request是对axios的封装,把他当作axios用就行
return http.request<R<any>>(
"get",
signModuleUrlApi(`/signup/sign-up-pict?id=${id}&semId=${semId}`),
// 一定要加, 否则axios会把二进制数据处理为json
{
responseType: "blob"
}
);
vue界面渲染
<template>
<!-- 忽略其它部分代码, 下面这货显示图片-->
<el-image :src="url" lazy />
<\template>
<script>
const url = ref();
// 发送请求
signApi.signUpPict(id, semId.value).then(
res => {
const blob = new Blob([res], { type: "image/png" });
// 创建URL对象
url.value = URL.createObjectURL(blob);
},
error => {
console.log(error);
ElMessage.error("系统错误, 无法生成二维码");
});
};
<\script>
注意事项
- 后端接口,最好不要有返回值,如果你设置了response.setContentType(“image/png”),很有可能在返回数据的时候出现序列化错误的bug
- 后端接口,最好对response的contentType设置一下,不然容易出现一些奇怪的bug
- 前端axios一定要设置responseType: “blob”,否则axios会把数据当成json处理
学习文章
https://zhuanlan.zhihu.com/p/474173086
https://www.jianshu.com/p/12fea9987c2d
更多推荐
已为社区贡献1条内容
所有评论(0)