Java后端调取微信小程序接口,创建微信小程序直播间

news2024/7/4 6:00:49

前提条件:

1.注册微信小程序

2.获取appId和secret秘钥

3.小程序具备直播权限

小程序直播开发文档网址

目录

1.创建和修改直播间

 2.删除直播间

3.获取直播间分享二维码


1.创建和修改直播间

两个功能一起写,区别在于,修改的时候需要多一个房间号属性。

1.根据开发文档创建直播间要发送以下JSON字段,所以创建一个实体类

 修改直播间需要发送以下JSON字段,比上面就多了一个roomId

 

2.创建微信直播间实体类

import java.util.Date;

/**
 * 调取微信接口创建直播间所用实体
 *
 * @author songrongzhen
 * @date 2023/05/05
 */
public class WechatzbjView {

    /**
     * 直播间房号
     */
    private Number id;

    /**
     * 直播间名字
     * 是否必填:是
     */
    private String name;

    /**
     * 背景图,填入mediaID(mediaID获取后,三天内有效)
     * 是否必填:是
     */
    private String coverImg;

    /**
     * 直播计划开始时间(开播时间需要在当前时间的10分钟后 并且 开始时间不能在 6 个月后)
     * 是否必填:是
     */
    private Number startTime;

    /**
     * 直播计划结束时间(开播时间和结束时间间隔不得短于30分钟,不得超过24小时)
     * 是否必填:是
     */
    private Number endTime;

    /**
     * 主播昵称
     * 是否必填:是
     */
    private String anchorName;

    /**
     * 主播微信号
     * 是否必填:是
     */
    private String anchorWechat;

    /**
     * 主播副号微信号
     * 是否必填:否
     */
    private String subAnchorWechat;

    /**
     * 创建者微信号
     * 是否必填:否
     */
    private String createrWechat;

    /**
     * 分享图,填入mediaID(mediaID获取后,三天内有效)
     * 是否必填:是
     */
    private String shareImg;

    /**
     * 购物直播频道封面图,填入mediaID(mediaID获取后,三天内有效)
     * 是否必填:是
     */
    private String feedsImg;

    /**
     * 是否开启官方收录 【1: 开启,0:关闭】,默认开启收录
     * 是否必填:否
     */
    private Number isFeedsPublic;

    /**
     * 直播间类型 【1: 推流,0:手机直播】
     * 是否必填:是
     */
    private Number type;

    /**
     * 是否关闭点赞 【0:开启,1:关闭】
     * 是否必填:是
     */
    private Number closeLike;

    /**
     * 是否关闭货架 【0:开启,1:关闭】
     * 是否必填:是
     */
    private Number closeGoods;

    /**
     * 是否关闭评论 【0:开启,1:关闭】
     * 是否必填:是
     */
    private Number closeComment;

    /**
     * 是否关闭回放 【0:开启,1:关闭】
     * 是否必填:否
     */
    private Number closeReplay;

    /**
     * 是否关闭分享 【0:开启,1:关闭】
     * 是否必填:否
     */
    private Number closeShare;

    /**
     * 是否关闭客服 【0:开启,1:关闭】
     * 是否必填:否
     */
    private Number closeKf;

我这里由于开发需求,需要在创建直播间的同时也需要把直播间的信息保存在自己的数据库中,所有我有创建了一个实体类,跟数据库字段对应,如需用到代码,自行生成set和get方法。

/**
 * 微信直播间实体
 *
 * @author songrongzhen
 * @date 2023/04/27
 */
@Entity
@Table(name = "HSGG_WECHATZBJ")
@DynamicInsert
@DynamicUpdate
public class Wechatzbj {

    @Id
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    @GeneratedValue(generator = "idGenerator") // 使用uuid的生成策略
    private String id;

    /**
     * 直播间名字
     * 是否必填:是
     */
    @Column
    @NotBlank(message = "直播间名字不能为空")
    private String name;

    /**
     * 背景图,填入mediaID(mediaID获取后,三天内有效)
     * 是否必填:是
     */
    @Column
    @NotBlank(message = "请上传背景图")
    private String coverImg;

    /**
     * 直播计划开始时间(开播时间需要在当前时间的10分钟后 并且 开始时间不能在 6 个月后)
     * 是否必填:是
     */
    @Column
    private Date startTime;

    /**
     * 直播计划结束时间(开播时间和结束时间间隔不得短于30分钟,不得超过24小时)
     * 是否必填:是
     */
    @Column
    private Date endTime;

    /**
     * 主播昵称
     * 是否必填:是
     */
    @Column
    @NotBlank(message = "主播昵称不能为空")
    private String anchorName;

    /**
     * 主播微信号
     * 是否必填:是
     */
    @Column
    @NotBlank(message = "主播微信号不能为空")
    private String anchorWechat;

    /**
     * 主播副号微信号
     * 是否必填:否
     */
    @Column
    private String subAnchorWechat;

    /**
     * 创建者微信号
     * 是否必填:否
     */
    @Column
    private String createrWechat;

    /**
     * 分享图,填入mediaID(mediaID获取后,三天内有效)
     * 是否必填:是
     */
    @Column
    @NotBlank(message = "请上传分享图")
    private String shareImg;

    /**
     * 购物直播频道封面图,填入mediaID(mediaID获取后,三天内有效)
     * 是否必填:是
     */
    @Column
    @NotBlank(message = "请上传购物直播频道封面图")
    private String feedsImg;

    /**
     * 是否开启官方收录 【1: 开启,0:关闭】,默认开启收录
     * 是否必填:否
     */
    @Column
    private Long isFeedsPublic;

    /**
     * 直播间类型 【1: 推流,0:手机直播】
     * 是否必填:是
     */
    @Column
    private Long type;

    /**
     * 是否关闭点赞 【0:开启,1:关闭】
     * 是否必填:是
     */
    @Column
    private Long closeLike;

    /**
     * 是否关闭货架 【0:开启,1:关闭】
     * 是否必填:是
     */
    @Column
    private Long closeGoods;

    /**
     * 是否关闭评论 【0:开启,1:关闭】
     * 是否必填:是
     */
    @Column
    private Long closeComment;

    /**
     * 是否关闭回放 【0:开启,1:关闭】
     * 是否必填:否
     */
    @Column
    private Long closeReplay;

    /**
     * 是否关闭分享 【0:开启,1:关闭】
     * 是否必填:否
     */
    @Column
    private Long closeShare;

    /**
     * 是否关闭客服 【0:开启,1:关闭】
     * 是否必填:否
     */
    @Column
    private Long closeKf;

    /**
     *主办方
     */
    @Column
    @NotBlank(message = "主办方不能为空")
    private  String zbf;

    /**
     * 机构id
     */
    @Column
    @NotBlank(message = "机构代码不能为空")
    private String deptCode;

    /**
     * 区划代码
     */
    @Column
    @NotBlank(message = "区划代码不能为空")
    private String regionCode;

    /**
     * 直播间状态
     * 101 正常
     *
     * 102 未开始
     *
     * 103 已结束
     *
     * 104 禁播
     *
     * 105 暂停中
     *
     * 106 异常(微信未创建成功)
     *
     * 107 已过期:表示直播间一直未开播
     */
    @Column
    private String status;

    /**
     * 创建直播间成功后返回的房间id
     */
    @Column
    private String roomId;


    /**
     * 创建日期
     */
    @Column
    private Date createDate;
    /**
     * 修改时间
     */
    @Column
    private Date modifyDate;

    /**
     * 创建人
     */
    @Column
    private String createUser;
    /**
     * 修改人
     */
    @Column
    private String modifyUser;

    /**
     * 背景图media_id
     */
    @Column
    private String coverImgMedia;

    /**
     * 分享图media_id
     */
    @Column
    private String shareImgMedia;

    /**
     * 购物直播频道封面图media_id
     */
    @Column
    private String feedsImgMedia;

    /**
     * 分享二维码
     */
    @Transient
    private String cdnUrl;

    /**
     * 分享路径
     */
    @Transient
    private String pagePath;

    /**
     * 分享海报
     */
    @Transient
    private String posterUrl;

准备好这两个实体类后开始三层架构代码

2.controller层代码创建

 /**
     * 新建(修改)直播间
     *
     * @param  wechatzbj
     * @return {@link ResponseResult}<{@link ?}>
     * @throws IOException ioexception
     */
    @RequestMapping("/save")
    @ResponseBody
    public ResponseResult<?> save(Wechatzbj wechatzbj) {
        return weChatzbManager.save(wechatzbj);
    }

3.service层代码

根据是否有房间号来判断是新建直播间还是修改直播间

在调取微信所有接口前先获取一个调取凭证access_token,开发文档

    /**
     * 创建直播间
     *
     * @param wechatzbj wechatzbj
     * @return {@link ResponseResult}<{@link ?}>
     */
    public ResponseResult<?> save(Wechatzbj wechatzbj);


以上是接口
以下是实现

/**
     * 创建/修改直播间
     *
     * @param wechatzbj wechatzbj
     * @return {@link ResponseResult}<{@link ?}>
     */
    @Override
    public ResponseResult<?> save(Wechatzbj wechatzbj) {
        //roomId为空创建直播间
        if(StringUtils.isEmpty(wechatzbj.getRoomId())) {
            try {
                String url = GET_TOKEN_URL + String.format("wxaapi/broadcast/room/create?access_token=%s", WeChartRequestUtils.getToken());
                getWechartZbj(wechatzbj,url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            
           return ResponseResultUtils.genResult("创建直播间成功");
        }
        //修改直播间
        else {
            try {
                String url = GET_TOKEN_URL + String.format("wxaapi/broadcast/room/editroom?access_token=%s", WeChartRequestUtils.getToken());
                getWechartZbj(wechatzbj,url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return ResponseResultUtils.genResult("直播间修改成功");
        }
    }

public void getWechartZbj(Wechatzbj wechatzbj,String url){
        WechatzbjView wechatzbjView = new WechatzbjView();
        if (StringUtils.isNotEmpty(wechatzbj.getRoomId())){
            wechatzbjView.setId( Long.parseLong(wechatzbj.getRoomId()));
        }
        wechatzbjView.setName(wechatzbj.getName());
        wechatzbjView.setCoverImg(wechatzbj.getCoverImgMedia());
        wechatzbjView.setStartTime(wechatzbj.getStartTime().getTime()/1000);
        wechatzbjView.setEndTime(wechatzbj.getEndTime().getTime()/1000);
        wechatzbjView.setAnchorName(wechatzbj.getAnchorName());
        wechatzbjView.setAnchorWechat(wechatzbj.getAnchorWechat());
        wechatzbjView.setSubAnchorWechat(wechatzbj.getSubAnchorWechat());
        wechatzbjView.setCreaterWechat(wechatzbj.getCreaterWechat());
        wechatzbjView.setShareImg(wechatzbj.getShareImgMedia());
        wechatzbjView.setFeedsImg(wechatzbj.getFeedsImgMedia());
        wechatzbjView.setIsFeedsPublic(wechatzbj.getIsFeedsPublic());
        wechatzbjView.setType(wechatzbj.getType());
        wechatzbjView.setCloseGoods(wechatzbj.getCloseGoods());
        wechatzbjView.setCloseLike(wechatzbj.getCloseLike());
        wechatzbjView.setCloseComment(wechatzbj.getCloseComment());
        wechatzbjView.setCloseReplay(wechatzbj.getCloseReplay());
        wechatzbjView.setCloseShare(wechatzbj.getCloseShare());
        wechatzbjView.setCloseKf(wechatzbj.getCloseKf());
        String param = JSONObject.toJSONString(wechatzbjView);
        //创建直播间/修改
        JSONObject jsonObject = OkHttpClientUtils.doPost(url, param);
        //直播间创建(修改)失败提示
        if (jsonObject.getInteger("errcode") != 0) {
            //保存到数据库,直播间状态为异常
            wechatzbj.setStatus("106");
            weChatzbDao.save(wechatzbj);
            System.err.println(jsonObject.get("errcode"));
            throw new RuntimeException(jsonObject.getString("errmsg"));
        }
        if (wechatzbj != null) {
            User user = UserUtils.getUser();
            wechatzbj.setCreateUser(user.getName());
            wechatzbj.setCreateDate(new Date());
            wechatzbj.setModifyDate(new Date());
            wechatzbj.setModifyUser(user.getName());
            wechatzbj.setStatus("101");
            if (StringUtils.isNotEmpty(jsonObject.getString("roomId"))) {
                wechatzbj.setRoomId(jsonObject.getString("roomId"));
            }
            //直播间信息保存到自己数据库
            weChatzbDao.save(wechatzbj);
        }
    }

我这里用的OkHttp发的请求,获取access_token工具类如下

public class WeChartRequestUtils {
    static final String GET_TOKEN_URL = "https://api.weixin.qq.com/";
    public static String getToken() throws IOException {
        String param = "cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
        String url = GET_TOKEN_URL + String.format(param, "", "");

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            if (response.body() != null) {
                JSONObject jsonObject = JSONObject.parseObject(response.body().string());
                if (Objects.nonNull(jsonObject.get("errcode"))) {
                    System.err.println(jsonObject.get("errcode"));
                    throw new RuntimeException(jsonObject.getString("errmsg"));
                } else {
                    return jsonObject.getString("access_token");
                }
            }
        } else {
            throw new RuntimeException("调用失败");
        }
        return null;
    }
}

service中还用了OKHttp去发送POST请求去调用微信接口创建直播间和修改直播间所以需要一个OKHttpUtils工具类。


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class OkHttpClientUtils {

    /**
     * 日志对象
     */
    private static Logger logger = LoggerFactory.getLogger(OkHttpClientUtils.class);
    private static final Long CONNECT_TIMEOUT = 10000L;
    private static final Long READ_TIMEOUT = 60000L;
    private static final Long WRITE_TIMEOUT = 60000L;

    public static String doGet(String url) {
        return doGet(url, READ_TIMEOUT, WRITE_TIMEOUT);
    }

    public static String doPost(String url) {
        return doPost(url, READ_TIMEOUT, WRITE_TIMEOUT);
    }

    /**
     * 设置编码集
     */
    private static final String ENCODE = "UTF-8";
    private static OkHttpClient client = new OkHttpClient();

    /**
     * get请求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static Response get(String url) throws IOException {

        OkHttpClient httpClient = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(80000, TimeUnit.SECONDS)
                .writeTimeout(80000, TimeUnit.SECONDS)
                .build();

        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = httpClient.newCall(request).execute();
        return response;
    }

    public static String doGet(String url, Long readTimeout, Long waiteTimeout) {
        String resultString = "";
        Response response = null;
        try {
            //******** 一、 创建 httpClient 对象***********
            OkHttpClient httpClient = new OkHttpClient.Builder()
                    .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                    .readTimeout(readTimeout, TimeUnit.SECONDS)
                    .writeTimeout(waiteTimeout, TimeUnit.SECONDS)
                    .build();


            // ******** 二、创建request 对象*************
            Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .build();

            //********* 三、发送请求 ********************

            response = httpClient.newCall(request).execute();

            //********* 四、对响应进行处理 ***************
            //1、如果 http 状态码不在 【200 ,300】区间内,抛出异常
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            // 因为服务器返回的数据可能非常大,所以必须通过数据流的方式来进行访问
            // 提供了诸如 string() 和 bytes() 这样的方法将流内的数据一次性读取完毕
            resultString = response.body().string();

            return resultString;
        } catch (SocketTimeoutException e) {
            // 超时
            //logger.error("executeHttpRequest TimeOut, e: " + e);
            System.out.println("executeHttpRequest TimeOut, e: " + e);
        } catch (IOException e) {
            // 网络IO异常
            System.out.println("executeHttpRequest IOException, e: " + e);
        } catch (Exception e) {
            // 其他异常
            e.printStackTrace();
        } finally {
            if (response != null) {
                // body 必须被关闭,否则会发生资源泄漏;
                response.body().close();
            }
        }
        return resultString;
    }

    public static String doPost(String url, Long readTimeout, Long waiteTimeout) {

        Response response = null;
        String resultString = "";
        try {
            //******* 一、创建 httpClient 对象 **********
            OkHttpClient httpClient = new OkHttpClient.Builder()
                    .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                    .readTimeout(readTimeout, TimeUnit.SECONDS)
                    .writeTimeout(waiteTimeout, TimeUnit.SECONDS)
                    .build();


            //******** 二、创建 request 对象 ************

            Request request = new Request.Builder()
                    .url(url)
                    .build();
            //******** 三、执行请求 ********************
            response = httpClient.newCall(request).execute();

            //******** 四、处理响应 ********************
            if (!response.isSuccessful()) {
                throw new IOException(" Unexpect code " + response);
            }

            resultString = response.body().string();

        } catch (SocketTimeoutException e) {
            // 超时
            System.out.println("executeHttpRequest TimeOut, e: " + e);
        } catch (IOException e) {
            // 网络IO异常
            System.out.println("executeHttpRequest IOException, e: " + e);
        } catch (Exception e) {
            // 其他异常
            e.printStackTrace();
        } finally {
            if (response != null) {
                // body 必须被关闭,否则会发生资源泄漏;
                response.body().close();
            }
        }
        return resultString;
    }

    public static JSONObject doPost(String url, String param) {
        // 获取的返回数据
        JSONObject result = new JSONObject();
        // 生成HttpClient对象并设置参数
        HttpClient httpClient = new HttpClient();
        // 设置Http连接超时为20秒
        HttpConnectionManagerParams params = httpClient.getHttpConnectionManager().getParams();
        params.setConnectionTimeout(20000);
        params.setSoTimeout(600000);
        // 生成postMethod对象并设置参数
        PostMethod postMethod = new PostMethod(url);
        // 设置请求重试处理:请求二次
        postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(1, true));
        postMethod.addRequestHeader("accept", "*/*");
        postMethod.addRequestHeader("connection", "Keep-Alive");
        // 设置json格式传送
        postMethod.addRequestHeader("Content-Type", "application/json;charset=UTF-8");
        // 封装请求数据
        try {
            RequestEntity requestEntity = new StringRequestEntity(param, "application/json", "UTF-8");
            postMethod.setRequestEntity(requestEntity);
        } catch (UnsupportedEncodingException e) {
            result.put("resultCode", 0);
            result.put("msg", "传输数据异常,请联系管理员!");
            e.printStackTrace();
        }
        // 发送请求,获取返回结果
        try {
            int code = httpClient.executeMethod(postMethod);
            if (code == HttpStatus.SC_OK) {
                String res = postMethod.getResponseBodyAsString();
                if (null != res && !"".equals(res)) {
                    result = JSON.parseObject(res);
                    result.put("resultCode", 1);
                } else {
                    result.put("resultCode", -2);
                    result.put("msg", "数据返回异常,请联系管理员!");
                }
            }
        } catch (IOException e) {
            result.put("resultCode", -1);
            result.put("msg", "请求异常,请联系管理员!");
            e.printStackTrace();
        } finally {
            postMethod.releaseConnection();
        }
        return result;
    }

    /**
     * GET请求
     *
     * @param url 请求的URL?拼参数
     * @throws IOException
     */
    public static String getToken(String url){
        try {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(url)
                    .build();
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                if (response.body() != null) {
                    JSONObject jsonObject = JSONObject.parseObject(response.body().string());
                    if (Objects.nonNull(jsonObject.get("errcode"))) {
                        System.err.println(jsonObject.get("errcode"));
                        throw new RuntimeException(jsonObject.getString("errmsg"));
                    } else {
                        return jsonObject.getString("access_token");
                    }
                }
            } else {
                throw new RuntimeException("调用失败");
            }
            throw new RuntimeException("调用失败");
        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new RuntimeException("调用失败");
    }
}

这样就完成了创建直播间和修改直播间,

创建完成微信会返回房间号,需要保存到数据库

 修改完直播间会返回errcode码

 2.删除直播间

删除直播间调取接口,参数1access_token参数2房间号,发送get请求,即可删除

3.获取直播间分享二维码

这里重点说一下,避坑

调取接口后微信会返回两个图片链接一个是直播间分享图另一个是分享海报,前段不能直接用<img>标签src“图片链接”去展示,具体怎么不能展示,大家可自己试一下(卖个关子)。。。

 所以就需要把返回的图片进行Base64转码,传给前段,然后前段去展示

1.controller层代码


    /**
     * 获取直播间分享二维码
     *
     * @param wechatzbj wechatzbj
     * @param model     模型
     * @return {@link String}
     */
    @RequestMapping("getsharedcode")
    public String getSharedCode(Wechatzbj wechatzbj, Model model){
        model.addAttribute("wechart",weChatzbManager.getSharedCode(wechatzbj));
        return "wechatzbj/sharedCodeView";
    }

2.service层

    /**
     * 获取直播间分享二维码
     *
     * @param wechatzbj
     * @return {@link String}
     */
    public Wechatzbj getSharedCode(Wechatzbj wechatzbj);


以上是接口
以下是实现

 /**
     * 获取直播间分享二维码
     *
     * @param wechatzbj wechatzbj
     * @return {@link String}
     */
    @Override
    public Wechatzbj getSharedCode(Wechatzbj wechatzbj) {
        String url = null;
        try {
            if (StringUtils.isNotEmpty(wechatzbj.getRoomId())){
                url = GET_TOKEN_URL + String.format("wxaapi/broadcast/room/getsharedcode?access_token=%s&roomId=%s", WeChartRequestUtils.getToken(),wechatzbj.getRoomId());
                Response response = OkHttpClientUtils.get(url);
                JSONObject jsonObject = JSONObject.parseObject(response.body().string());
                System.out.println("获取直播间分享二维码"+jsonObject);
                if (jsonObject.getInteger("errcode") != 0) {
                    System.err.println(jsonObject.get("errcode"));
                    throw new RuntimeException(jsonObject.getString("errmsg"));
                }
                wechatzbj.setCdnUrl(ImageUtils.toBase64(jsonObject.getString("cdnUrl")));
                wechatzbj.setPagePath(jsonObject.getString("pagePath"));
                wechatzbj.setPosterUrl(ImageUtils.toBase64(jsonObject.getString("posterUrl")));
                return wechatzbj;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new Wechatzbj();
    }

图片转Base64工具类(JDk8)

给一个图片链接返回该图片的Base64编码

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Base64;

public class ImageUtils {
    public static String toBase64(String imageUrl) throws IOException {
        URL url = new URL(imageUrl);
        try (InputStream is = url.openStream();
             ByteArrayOutputStream os = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[4096];
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            return Base64.getEncoder().encodeToString(os.toByteArray());
        }
    }
}

当然你用的JDK是11的话可以这么写

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Base64;

public class ImageUtils {
    public static String toBase64(String imageUrl) throws IOException {
        URL url = new URL(imageUrl);
        InputStream is = url.openStream();
        byte[] bytes = is.readAllBytes();
        return Base64.getEncoder().encodeToString(bytes);
    }
}

把转码后的编码传给前段,前段用以下方式去展示。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>展示Base64图片</title>
</head>
<body>
  < img id="myImage" alt="图片">
  
  <script>
    // 假设我们从后端获取了一个名为base64Str的Base64字符串
    const base64Str = "data:image/png;base64,iVBORw0KGg...";

    // 获取img元素并设置src属性为Base64字符串
    const img = document.getElementById("myImage");
    img.src = base64Str;
  </script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/514788.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数字化转型-05】数字化转型中战略驱动的利器——平衡计分卡

今年的4月19日&#xff0c; 华为第20届全球分析师大会上&#xff0c;华为孟晚舟在大会上发表了“初心如磐&#xff0c;奋楫笃行&#xff0c;共赢数字化未来”的主题演讲&#xff0c;其中分享了对数字化转型的三个核心洞见&#xff0c;首先&#xff0c;战略驱动是根本&#xff0…

Mojo:比 Python 快 35000 倍的 AI 编程语言

Mojo&#xff1a;比 Python 快 35000 倍的 AI 编程语言 Mojo是一门刚刚发布的面向 AI 开发人员的编程语言。 Mojo 被设计为 Python 的超集&#xff0c;所以如果你已经掌握了 Python&#xff0c;学习 Mojo 会很容易。关键是 Mojo 将 Python 的易用性与 C 语言的性能相结合&am…

AIGC—— 内容生产力革命的起点

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.AIGC 1.什么是AIGC? 2.AIGC有哪些优势与挑战 &#xff08;1&#xff0…

51单片机(十)DS1302实时时钟

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

Solon 框架,单月下载量突破100万了!!!

Solon 框架&#xff0c;单月下载量突破100万了。感谢开源的力量和社区的支持&#xff0c;我们同喜同荣&#xff01;&#xff01;&#xff01;目前&#xff0c;作为新成员加入了“可信开源共同体”&#xff0c;也积极参与中科院的“开源之夏”计划&#xff0c;也备受某军工服务商…

【C++入门】你知道C++为什么会有内联函数吗?

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

深度优先遍历和广度优先遍历

深度优先遍历和广度优先遍历 文章目录 深度优先遍历和广度优先遍历图图的实现遍历方式深度优先遍历基本思想广度优先遍历基本思想 完整代码 图 介绍&#xff1a;用于表示多对多的关系 图是一种数据结构&#xff0c;其中结点可以具有零个或多个相邻元素。两个结点之间的连接称…

FFmpeg AAC 解码 PCM

1. 概要与流程图 1.1 AAC 转 PCM,需要解码库来实现,目前了解有三种方式,当前使用的是 FFmpeg 库解码 1) faad 解码库网址:faadhttps://sourceforge.net/projects/faac/files/faad2-src/ 2) fdk-aac 编解码库网址: fdk-aac

接口测试入门:轻松掌握 ,让你的后端“心甘情愿”地配合你

目录 前言 简介 什么是API测试&#xff1f; API测试的必要性 API测试的类型 优势 API测试的挑战 【自动化测试工程师学习路线】 前言 在这篇文章中&#xff0c;我将带你轻松入门接口测试并掌握实用技巧&#xff0c;让你能够与后端开发人员更加顺畅地合作。相信我&…

【量化分析】用mplfinance显示交易图时,处理 Expect data.index as DatetimeIndex?

目录 一、说明 二、程序代码和出错描述 三、合理化建议 3.1 读入数据时指定索引 3.2 读入数据后&#xff0c;使用数据前指定日期&#xff08;时间戳&#xff09;索引 一、说明 我打算从比特币数据中获取烛台图。这是我在加载 csv 文件后选择我想要的数据框的代码。然而&…

【2】Kaggle:狗的种类识别,基于论文中的 VGG(11)/ResNet(18)/SENet 结构实现

1.数据集格式 在前面【1】中已经对数据集进行过了处理,在自己实现这一模块,训练数据集的统一格式为下图: 2.VGG11结构 根据论文Karen Simonyan, Andrew Zisserman. Very deep convolutional networks for large-scale image recognition. ICLR, 2015. (VGG) 中的结构,根…

如何在华为云服务器安装MindSpore框架

参考链接 一、获取安装命令 我是在华为云租了一个云服务器&#xff0c;然后系统是Ubuntu18.04,如果不知道自己的系统&#xff0c;可以通过以下方式&#xff1a; 第三方依赖安装方法 1.确认安装Ubuntu 18.04是64位操作系统 确认系统版本号&#xff0c;在终端输入lsb_release…

Linux -- 进阶 Web服务器 虚拟主机 --- 基于 IP 地址

虚拟主机 一个Web 服务器&#xff0c;如果只能运行一个网站的话&#xff0c;那么对于一些经费不是很足的小公司来说&#xff0c;那就 有些奢侈了&#xff0c;资源没有办法完全利用上 &#xff08; 无论是 内存&#xff0c;CPU&#xff0c;硬盘&#xff0c;带宽等等 &#xff0…

【网络常用命令汇总】ping和ipconfig命令、nslookup命令、netstat和tracert命令、route和arp命令详解(附图详解)

【写在前面】由于考试将近我也是临时抱个佛脚&#xff0c;之前对网络这块的概念真的只是停留在大学里面学的计算机网络&#xff0c;但是当时并没有接触这些实在的东西&#xff0c;也就只有工作后才会去想那么多&#xff0c;比如网络连通性ping一下就知道&#xff0c;其他的更不…

第07讲:Java High Level Client,读写 ES 利器

SkyWalking OAP 后端可以使用多种存储对数据进行持久化&#xff0c;例如 MySQL、TiDB 等&#xff0c;默认使用 ElasticSearch 作为持久化存储&#xff0c;在后面的源码分析过程中也将以 ElasticSearch 作为主要存储进行分析。 ElasticSearch 基本概念 本课时将快速介绍一下 E…

【类和对象完结篇】

目录 ❀初始化列表 构造函数体赋值 初始化列表 ❀explicit关键字 ❀static成员 什么是static成员&#xff1f; 特性 ❀友元 友元函数 友元类 ❀内部类 ❀理解类和对象 &#x1f340;​​​​​​​​​​​​​​小结&#x1f340; &#x1f389;博客主页&#xf…

linux环境安装使用mysql详解

01-安装MySQL并启动 1.1 环境准备 # 1.卸载mariadb&#xff0c;否则安装mysql会出现冲突 &#xff08;1&#xff09;.执行命令rpm -qa | grep mariadb 会列出所有被安装的mariadb rpm 包&#xff1b; &#xff08;2&#xff09;.执行命令rpm -e --nodeps mariadb-libs-5.5.56…

super_排列组合lesson08易错题记录

此题用插空法解决&#xff1a;这个是组合的问题&#xff0c;总共10个学生&#xff0c;要分配到7个班级里&#xff0c;也就是要把这十个学生分为7部分&#xff0c;如果让学生们站在一起&#xff0c;就是在9个空位中插入6块木板&#xff0c;也就是C(9,6)也就是84 此题用捆绑法解决…

[Java进阶] 线程池详解

文章目录 前言1. 线程池的作用2. 线程池的应用3. 标准库中创建线程池的方式 前言 本文介绍线程池的作用和实现方法. 1. 线程池的作用 1.我们知道,线程的作用是由于进程的创建和销毁需要分配和回收资源,开销较大.而线程是"轻量级进程",创建销毁更高效. 2.线程池,比线…

汽车发动机点火性能测试仪设计

汽车发动机的点火系统包括上百种电气和机械零部件&#xff0c;生产线分布较广&#xff0c;因此分布式间接监控方式在点火系统的监测与故障诊断系统中得到广泛应用。发动机点火性能测试仪通过测量发动机的闭合角与分火角&#xff0c;对其分电器和点火器性能进行分析。 闭合角、分…