springboot实战代码之如何优雅地返回图片

springboot实战代码:【如何优雅地返回图片】
本文将会总结返回图片地常用方法:

  1. 流方式返回:主要是实现方式不一样,基于response和HttpConvertMessage
  2. base64返回
说明 图片可以来自很多地方,可以是本地文件夹,也可以是网络流,或是数据库二进制,这里为了简单起见,就用本地文件。
@RestController @RequestMapping("/") public class ImgController {private String imgPath = "E:\\meme.png"; private InputStream getImgInputStream() throws FileNotFoundException { return new FileInputStream(new File(imgPath)); }

依赖 【springboot实战代码之如何优雅地返回图片】下面使用的IOUtils大家都应该很熟悉了,来自经典的common-io模块
commons-io commons-io 2.6

1.基于response返回 非常基础也简单的方式:
import org.apache.commons.io.IOUtils; import org.springframework.http.MediaType; /** * 使用response输出图片流 */ @GetMapping("/img-response") public void getImage(HttpServletResponse resp) throws IOException { final InputStream in = getImgInputStream(); resp.setContentType(MediaType.IMAGE_PNG_VALUE); IOUtils.copy(in, resp.getOutputStream()); }

2.基于produces返回字节流 2.1返回裸字节流 我们先来看如果直接返回图片的字节流是什么情况:
/** * 试试直接返回字节流,不指定content-type */ @GetMapping(value = "https://www.it610.com/img-byte") public byte[] getImageByte() throws IOException { final InputStream in = getImgInputStream(); return IOUtils.toByteArray(in); }

结果如下:乱码了,因为content-type不对
springboot实战代码之如何优雅地返回图片
文章图片

2.2指定content-type返回字节流 使用produces指定类型:这里我们指定2种类型,看看会发生什么
@GetMapping(value = "https://www.it610.com/img-media-type", produces = {MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE}) public byte[] getImage() throws IOException { final InputStream in = getImgInputStream(); return IOUtils.toByteArray(in); }

图片可以正常返回,但是仔细一看,response header里的content-typeimage/jpeg
springboot实战代码之如何优雅地返回图片
文章图片

原因在于当我们默认请求时,springboot匹配地第一种类型jpeg,虽然我们是png图片。
那我们如何让其返回地content-type为image/png呢?
通过读取源码注释我们知道:
springboot实战代码之如何优雅地返回图片
文章图片

只需要在请求时传我们想要地Accept就可以了,下面是postman地示例:
springboot实战代码之如何优雅地返回图片
文章图片

事实上,这个方法还可以对我们上面的/img-byte接口使用,就不会返回乱码了
springboot实战代码之如何优雅地返回图片
文章图片

同时,如果我们传了不支持的类型,会得到406错误:
springboot实战代码之如何优雅地返回图片
文章图片

2.3直接下载图片文件 如果我们想直接弹出下载框,那么可以指定content-type为:application/octet-stream
@GetMapping(value = "https://www.it610.com/img-file.png", produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE}) public byte[] getImageFile() throws IOException { final InputStream in = getImgInputStream(); return IOUtils.toByteArray(in); }

springboot实战代码之如何优雅地返回图片
文章图片

@GetMapping(value = "https://www.it610.com/img/{iconId}", produces = {MediaType.IMAGE_PNG_VALUE, MediaType.IMAGE_JPEG_VALUE}) public byte[] getImage(@PathVariable String iconId) throws IOException { final GisIcon icon = iconService.getById(iconId); if (icon == null) { throw new IllegalArgumentException("不存在此图片"); } final FileInputStream fio = new FileInputStream(new File(iconService.getSavePath(icon.getUsername(), icon.getName(), icon.getId()))); byte[] bytes = new byte[fio.available()]; log.info("读取文件结果:{}", fio.read(bytes, 0, fio.available())); return bytes; }

3.base64图片
import java.util.Base64; @GetMapping("/img-base64") public String getBase64Img() throws IOException { final byte[] bytes = IOUtils.toByteArray(getImgInputStream()); return Base64.getEncoder().encodeToString(bytes); }

前端接收:
function reqListener (base64) { var body = document.getElementsByTagName("body"); var img = document.createElement("img"); img.src = "data:image/png; base64, "+base64; body.appendChild(img); }var oReq = new XMLHttpRequest(); oReq.addEventListener("load", reqListener); oReq.open("GET", "http://localhost:8013/img-base64"); oReq.send();

    推荐阅读