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

三、总结

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

记录下!

相关推荐
JH30736 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
qq_12498707539 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_9 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
2301_818732069 小时前
前端调用控制层接口,进不去,报错415,类型不匹配
java·spring boot·spring·tomcat·intellij-idea
汤姆yu13 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
暮色妖娆丶13 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
biyezuopinvip14 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
JavaGuide14 小时前
一款悄然崛起的国产规则引擎,让业务编排效率提升 10 倍!
java·spring boot
figo10tf15 小时前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
zhangyi_viva15 小时前
Spring Boot(七):Swagger 接口文档
java·spring boot·后端