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

三、总结

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

记录下!

相关推荐
MC丶科4 小时前
【SpringBoot 快速上手实战系列】5 分钟用 Spring Boot 搭建一个用户管理系统(含前后端分离)!新手也能一次跑通!
java·vue.js·spring boot·后端
lang201509286 小时前
Spring Boot 入门:5分钟搭建Hello World
java·spring boot·后端
Javashop_jjj7 小时前
三勾软件| 用SpringBoot+Element-UI+UniApp+Redis+MySQL打造的点餐连锁系统
spring boot·ui·uni-app
PHP源码7 小时前
SpringBoot校园二手商城系统
java·spring boot·springboot二手商城·java校园二手商城系统
毕业设计制作和分享7 小时前
springboot159基于springboot框架开发的景区民宿预约系统的设计与实现
java·spring boot·后端
MC丶科9 小时前
【SpringBoot常见报错与解决方案】端口被占用?Spring Boot 修改端口号的 3 种方法,第 3 种 90% 的人不知道!
java·linux·spring boot
计算机学长felix9 小时前
基于SpringBoot的“中学信息技术课程教学网站”的设计与实现(源码+数据库+文档+PPT)_2025-10-17
数据库·spring boot·后端
Luffe船长10 小时前
前端vue2+js+springboot实现excle导入优化
前端·javascript·spring boot
周杰伦_Jay10 小时前
【Spring Boot从入门到精通】原理、实战与最佳实践
java·spring boot·后端