SpringBoot接口中如何直接返回圖片數(shù)據(jù)
接口直接返回圖片數(shù)據(jù)
起因
最近在做涉及到分享推廣的業(yè)務(wù),需要由業(yè)務(wù)員分享二維碼進(jìn)入推廣頁(yè)面,由于是新項(xiàng)目,前期預(yù)算和用量都有限,沒(méi)有搭建對(duì)象存儲(chǔ)服務(wù),所以決定使用后臺(tái)服務(wù)動(dòng)態(tài)生成二維碼圖片直接圖片數(shù)據(jù)并返回。
首先是二維碼的生成,決定使用google的zxing,畢竟google的東西還是不錯(cuò)的,maven添加依賴如下:
<!-- https://mvnrepository.com/artifact/com.google.zxing/core --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.3</version> </dependency> <!-- https://mvnrepository.com/artifact/com.google.zxing/javase --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.3</version> </dependency>
繼續(xù)查zxing的使用方法,發(fā)現(xiàn)大多數(shù)都是生成二維碼然后寫成圖片文件的,不太適合我現(xiàn)在的情況。
類似這種
Map hints = new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); hints.put(EncodeHintType.MARGIN, 2); BitMatrix qrcode = new QRCodeWriter().encode(href, BarcodeFormat.QR_CODE, 300, 300); //網(wǎng)上的方案大多數(shù)都是通過(guò)io流寫到文件系統(tǒng), MatrixToImageWriter.writeToStream(qrcode,"png",response.getOutputStream());
于是企圖用response的輸出流返回,但是返回的數(shù)據(jù)瀏覽器看到的全是亂碼,這種方案并沒(méi)有成功
根據(jù)個(gè)人經(jīng)驗(yàn)
一般這種開(kāi)源方案既然二維碼數(shù)據(jù)BitMatrix對(duì)象都生成了,肯定有獲取原始數(shù)據(jù)的方法,點(diǎn)進(jìn)MatrixToImageWriter類搜索方法,果然,找到了能直接返回BufferedImage對(duì)象的方法
現(xiàn)在,BufferedImage對(duì)象已經(jīng)有了,只差把它扔回前端了,繼續(xù)百度,發(fā)現(xiàn)可以直接返回該對(duì)象,類似以下配置
@GetMapping(value = "/qrcode", produces = MediaType.IMAGE_JPEG_VALUE) @ResponseBody public BufferedImage generateQRCode() { //返回BufferedImage的對(duì)象 }
以為問(wèn)題即將解決,然而瀏覽器訪問(wèn)返回406,上網(wǎng)一查,原來(lái)是沒(méi)有對(duì)應(yīng)消息類型的轉(zhuǎn)換器導(dǎo)致的,有博主提到需要如下配置
@Bean public BufferedImageHttpMessageConverter addConverter(){ return new BufferedImageHttpMessageConverter(); }
加了上面的配置后發(fā)現(xiàn)問(wèn)題仍沒(méi)有解決,報(bào)錯(cuò)仍是406,懷疑配置沒(méi)有生效,于是決定走源碼查看原因。debug源碼時(shí)發(fā)現(xiàn)messageConverters的list中確實(shí)沒(méi)有我配置的,說(shuō)明的確是配置問(wèn)題,查找messageConverters的set操作,查到如圖的地方
發(fā)現(xiàn)springMVC是在配置RequestMappingHandlerAdapter設(shè)置的HttpMessageConverter,進(jìn)入getMessageConverters()方法
根據(jù)我的工地英語(yǔ)8級(jí),extendMessageConverters這個(gè)方法應(yīng)該是在添加自定義的HttpMessageConverter,進(jìn)入該方法
空實(shí)現(xiàn),很明顯估計(jì)是模板模式,需要自己去擴(kuò)展,于是自己寫了一個(gè)配置類繼承WebMvcConfigurationSupport,重寫extendMessageConverters方法
@Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new BufferedImageHttpMessageConverter()); }
瀏覽器再訪問(wèn),二維碼圖片展示,問(wèn)題解決
總結(jié):實(shí)現(xiàn)一個(gè)方案的過(guò)程中碰到了各種各樣的奇怪問(wèn)題,最好的方式是先網(wǎng)上找資料快速解決問(wèn)題,如果無(wú)法解決,再通過(guò)自己走源碼的方式從根本原因上尋找出現(xiàn)問(wèn)題的原因,解決問(wèn)題最復(fù)雜的地方是定位問(wèn)題,問(wèn)題定位了,解決便不再是難題
優(yōu)雅的實(shí)現(xiàn)圖片返回
注意:response.setContentType("image/png");這行代碼一定要加上
@RestController @Slf4j @Api(tags = SwaggerConfig.TAG_IMAGE) @RequestMapping(SwaggerConfig.TAG_IMAGE) public class ImageController { ? ? @Resource ? ? private HttpServletResponse response; ? ? @GetMapping(value = "/getImage") ? ? @ApiOperation("獲取圖片-以ImageIO流形式寫回") ? ? public void getImage() throws IOException { ? ? ? ? OutputStream os = null; ? ? ? ? try { // ? ? ? ?讀取圖片 ? ? ? ? ? ? BufferedImage image = ImageIO.read(new FileInputStream(new File("F:\\谷歌下載\\未命名文件.png"))); ? ? ? ? ? ? response.setContentType("image/png"); ? ? ? ? ? ? os = response.getOutputStream(); ? ? ? ? ? ? if (image != null) { ? ? ? ? ? ? ? ? ImageIO.write(image, "png", os); ? ? ? ? ? ? } ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? log.error("獲取圖片異常{}",e.getMessage()); ? ? ? ? } finally { ? ? ? ? ? ? if (os != null) { ? ? ? ? ? ? ? ? os.flush(); ? ? ? ? ? ? ? ? os.close(); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot日志開(kāi)啟SLF4J過(guò)程解析
這篇文章主要介紹了Springboot日志開(kāi)啟SLF4J過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05IDEA 自帶的數(shù)據(jù)庫(kù)工具真的很牛逼(收藏版)
這篇文章主要介紹了IDEA 自帶的數(shù)據(jù)庫(kù)工具真的很牛逼(收藏版),本文以 IntelliJ IDEA/ Mac 版本作為演示,其他版本的應(yīng)該也差距不大,需要的朋友可以參考下2021-04-04Hibernate中實(shí)現(xiàn)增刪改查的步驟詳解
本篇文章主要介紹了Hibernate中實(shí)現(xiàn)增刪改查的步驟與方法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02IDEA創(chuàng)建Servlet編寫HelloWorldServlet頁(yè)面詳細(xì)教程(圖文并茂)
在學(xué)習(xí)servlet過(guò)程中參考的教程是用eclipse完成的,而我在練習(xí)的過(guò)程中是使用IDEA的,在創(chuàng)建servlet程序時(shí)遇到了挺多困難,在此記錄一下,這篇文章主要給大家介紹了關(guān)于IDEA創(chuàng)建Servlet編寫HelloWorldServlet頁(yè)面詳細(xì)教程的相關(guān)資料,需要的朋友可以參考下2023-10-10Java 關(guān)鍵字 volatile 的理解與正確使用
本文主要介紹 volatile 的使用準(zhǔn)則,以及使用過(guò)程中需注意的地方,感興趣的朋友一起看看吧2017-06-06Java實(shí)現(xiàn)簡(jiǎn)易的洗牌和發(fā)牌功能
本文主要介紹了Java實(shí)現(xiàn)簡(jiǎn)易的洗牌和發(fā)牌功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04SpringCloud實(shí)戰(zhàn)小貼士之Zuul的路徑匹配
這篇文章主要介紹了SpringCloud實(shí)戰(zhàn)小貼士之Zuul的路徑匹配,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10