后端图片数据返回
后端通过二进制流的形式,写入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*/@Overridepublic 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