SpringBoot接口中如何直接返回图片数据

2023-09-19 22:24:48

SpringBoot接口中如何直接返回图片数据

目录
  • 接口直接返回图片数据

  • 起因

  • 类似这种

  • 根据个人经验

  • 优雅的实现图片返回

接口直接返回图片数据

起因

最近在做涉及到分享推广的业务,需要由业务员分享二维码进入推广页面,由于是新项目,前期预算和用量都有限,没有搭建对象存储服务,所以决定使用后台服务动态生成二维码图片直接图片数据并返回。

首先是二维码的生成,决定使用google的zxing,毕竟google的东西还是不错的,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>

继续查zxing的使用方法,发现大多数都是生成二维码然后写成图片文件的,不太适合我现在的情况。

类似这种

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);
//网上的方案大多数都是通过io流写到文件系统,
MatrixToImageWriter.writeToStream(qrcode,"png",response.getOutputStream());

于是企图用response的输出流返回,但是返回的数据浏览器看到的全是乱码,这种方案并没有成功

根据个人经验

一般这种开源方案既然二维码数据BitMatrix对象都生成了,肯定有获取原始数据的方法,点进MatrixToImageWriter类搜索方法,果然,找到了能直接返回BufferedImage对象的方法

现在,BufferedImage对象已经有了,只差把它扔回前端了,继续百度,发现可以直接返回该对象,类似以下配置

@GetMapping(value = "/qrcode", produces = MediaType.IMAGE\_JPEG\_VALUE)
@ResponseBody
public BufferedImage generateQRCode() {
        //返回BufferedImage的对象
    }

以为问题即将解决,然而浏览器访问返回406,上网一查,原来是没有对应消息类型的转换器导致的,有博主提到需要如下配置

@Bean
    public BufferedImageHttpMessageConverter addConverter(){
        return new BufferedImageHttpMessageConverter();
    }

加了上面的配置后发现问题仍没有解决,报错仍是406,怀疑配置没有生效,于是决定走源码查看原因。debug源码时发现messageConverters的list中确实没有我配置的,说明的确是配置问题,查找messageConverters的set操作,查到如图的地方

发现springMVC是在配置RequestMappingHandlerAdapter设置的HttpMessageConverter,进入getMessageConverters()方法

根据我的工地英语8级,extendMessageConverters这个方法应该是在添加自定义的HttpMessageConverter,进入该方法

空实现,很明显估计是模板模式,需要自己去扩展,于是自己写了一个配置类继承WebMvcConfigurationSupport,重写extendMessageConverters方法

    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new BufferedImageHttpMessageConverter());
    }

浏览器再访问,二维码图片展示,问题解决

**总结:**实现一个方案的过程中碰到了各种各样的奇怪问题,最好的方式是先网上找资料快速解决问题,如果无法解决,再通过自己走源码的方式从根本原因上寻找出现问题的原因,解决问题最复杂的地方是定位问题,问题定位了,解决便不再是难题

优雅的实现图片返回

注意: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();
            }
        }
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

最新评论

最近更新的内容
更多推荐

【map、set的封装】

目录前言一、map、set的框架搭建二、map、set的迭代器的封装2.1、map、set的迭代器的初步封装2.2、map、set的const迭代器的封装2.2.1、set的const迭代器的封装2.2.2、map的const迭代器的封装三、operator[]四、代码实现前言本文的代码是基于前一篇文章的红黑树的代码来

vue类与样式的绑定&&列表渲染

目录1.类与样式的绑定1.1绑定HTMLclass1.2绑定数组1.3绑定内联样式绑定数组2.列表渲染2.1v-for​2.2v-for与对象2.3在v-for里使用范围值​1.类与样式的绑定1.1绑定HTMLclass我们可以给:class(v-bind:class的缩写)传递一个对象来动态切换class:<div:

java操作es集群模糊查询等

首先引入依赖<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.17.13</version></dependency

linux安装配置 flume

目录一解压安装包二配置部署(1)修改配置(2)下载工具(3)创建配置文件(4)启动监听测试(5)flume监控文件一解压安装包这里提供了网盘资源链接:https://pan.baidu.com/s/1Z0aItCHMybYpXkt3_RUaVw?pwd=s6pg提取码:s6pg这里安装包是放到/opt/install文

Java中List转字符串的方法

一、使用String.join方法在Java8之后,String类增加了一个静态方法join(),可以方便地将列表中的元素连接成字符串。//创建ListList<String>list=Arrays.asList("Google","Baidu","Taobao");//以逗号分隔的形式输出整个列表Stringresu

微服务保护

1.初识Sentinel1.1.雪崩问题及解决方案1.雪崩问题微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务。如图,如果服务提供者I发生了故障,当前的应用的部分业务因为依赖于服务I,因此也会被阻塞。此时,其它不依赖于服务I的业务似乎不受影响。但是,依赖服务I的业务请求被阻塞,用户不会得到响应,则t

在c#中使用CancellationToken取消任务

目录🚀介绍:🐤简单举例🚀IsCancellationRequested🚀ThrowIfCancellationRequested🐤在控制器中使用🚀通过异步方法的参数使用cancellationToken🚀api结合ThrowIfCancellationRequested()🚀介绍:Cancellatio

POJ 3185 The Water Bowls 反转+点灯游戏

一、题目大意有20盏灯(其实20盏灯数据量太少了,1e7我觉得差不多都可以过)放在同一行,点亮某一盏灯,它左右两边的灯也会亮,然后边缘特殊考虑,电亮两端的灯,只会照亮它相邻的那一个。二、解题思路这其实就是一个反转问题,我们从第二盏灯开始循环到第20盏灯,对于每一次循环的i,我们计算出i-1的灯是否亮着,如果i-1亮着,

Golang 中的匿名变量详解

在Golang中,可以使用匿名变量来忽略不需要的返回值或占位符。匿名变量是一种特殊类型的变量,可以简化代码并提高可读性。本文将详细介绍匿名变量的定义、特性和使用方法。什么是匿名变量?在Golang中,匿名变量是一种没有显式声明名称的变量,通常用于在需要临时存储值但不需要在后续代码中使用该值的情况。匿名变量的声明方式是使

吃瓜教程第一二章学习记录

当大多数人听到"机器学习"时,他们会联想到机器人:一个可靠的管家或一个致命的终结者,这取决于你问谁。但是,机器学习并不只是未来主义的幻想,它已经存在了。事实上,在一些特殊的应用中,如光学字符识别(OCR)等,已经有了几十年的历史。但是第一个真正主流的ML应用是在20世纪90年代:垃圾邮件过滤器,它改善了数亿人的生活,并

【GPU编程】Visual Studio创建基于GPU编程的项目

vs创建基于GPU编程的项目🍊前言🐸方法一-CUDARuntime生成😝debug设置🍅方法二-空项目配置🍉🍉🍉代码验证🍊前言cuda以及cudnn的安装以及系统环境变量的配置默认已经做完。如果没有安装好配置好的,可以参考其他的博客。本博客只为记录在完成以上配置后,如何在vs端创建GPU编程的项目。🐸

热文推荐