java-后端调用第三方接口返回图片流给前端

一、背景

有个需求是这样的,客户端直接通过外网访问oss获取图片需要额外付费,考虑到成本问题,修改技术方案为:客户端将请求链接发给后端,后端根据请求做一定的截取或拼接,通过内网调用oss,再将下载下来的图片流返回给前端。

图片流,展现在页面上就是直接返回一张图片在浏览器上。

二、具体代码展示

前端期望,如果异常,直接把http status返回非200

java 复制代码
@Slf4j
@RestController
public class PictureController {
    @Autowired
    private PictureService pictureService;

    @RequestMapping(value = "getPicture")
    public void getPicture(String path, HttpServletResponse resp) {
        boolean picSuccess;
        // 注意:一定要有这步,否则图片显示不出来
        resp.setContentType(MediaType.IMAGE_JPEG_VALUE);
        long start = System.currentTimeMillis();
        try {
            picSuccess = pictureService.getOssPicture(path, resp);
            if (!picSuccess) {
                resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
            }
        } catch (Exception e) {
            resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
            log.error("下载图片失败!!");
        }
        log.info("cmd=/getPicture,param={},cost:{}", path, System.currentTimeMillis() - start);
    }
}
java 复制代码
public interface PictureService {
    boolean getOssPicture(String path, HttpServletResponse resp) throws IOException;
}
java 复制代码
@Slf4j
@Service
public class PictureServiceImpl implements PictureService {
    
    @Value("${alioss.ak}")
    private String accessKeyId;

    // http://*********.aliyuncs.com
    @Value("${url.prefix}")
    private String urlPrefix;

    @Value("${oss.connect.time:3000}")
    private int ossConnectTime;

    @Override
    public boolean getOssPicture(String path, HttpServletResponse resp) throws IOException {
        String url = getOssUrl(path);
        long st = System.currentTimeMillis();
        Request requestDownload = new Request.Builder()
                .url(url)
                .build();
        OkHttpClient client = new OkHttpClient();
        client = client.newBuilder().connectTimeout(ossConnectTime, TimeUnit.MILLISECONDS).build();
        Response responseDownload = client.newCall(requestDownload).execute();
        if (responseDownload.isSuccessful() && responseDownload.body() != null && responseDownload.body().byteStream() != null) {
            InputStream is = responseDownload.body().byteStream();
            writeImageFile(resp, is);
        } else {
            log.error("PictureServiceImpl-oss调用返回异常: url={}, data={}", url, responseDownload);
            return false;
        }
        long responseTime = System.currentTimeMillis() - st;
        log.info("request-oss cost:{}", responseTime);
        return true;
    }

    // base64解码==这块是与前端约定好的,我这边要做的解码
    private String getOssUrl(String path) throws UnsupportedEncodingException {
        final Base64.Decoder decoder = Base64.getDecoder();
        String decodePath = new String(decoder.decode(path), "UTF-8");
        StringBuffer buffer = new StringBuffer();
        String[] split = decodePath.split("&");
        for (int i = 0; i < split.length; i++) {
            if (!split[i].startsWith("Version")) {
                buffer.append(split[i]).append("&");
            }
        }
        log.info("getOssUrl={}", urlPrefix + buffer);
        buffer.append("OSSAccessKeyId=").append(accessKeyId);
        return urlPrefix + buffer;
    }

    /**
     * 将输入流输出到页面
     *
     * @param resp
     * @param inputStream
     */
    public void writeImageFile(HttpServletResponse resp, InputStream inputStream) {
        OutputStream out = null;
        try {
            out = resp.getOutputStream();
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = inputStream.read(b)) != -1) {
                out.write(b, 0, len);
            }
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

三、总结

上面就是返回图片流的方式;

记录下!

相关推荐
皮皮林55117 小时前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
用户908324602733 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840824 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解4 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解4 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记4 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者5 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840825 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解5 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
初次攀爬者6 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq