赞
踩
有个需求是这样的,客户端直接通过外网访问oss获取图片需要额外付费,考虑到成本问题,修改技术方案为:客户端将请求链接发给后端,后端根据请求做一定的截取或拼接,通过内网调用oss,再将下载下来的图片流返回给前端。
图片流,展现在页面上就是直接返回一张图片在浏览器上。
前端期望,如果异常,直接把http status返回非200
- @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);
- }
- }
- public interface PictureService {
- boolean getOssPicture(String path, HttpServletResponse resp) throws IOException;
- }
- @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();
- }
- }
- }
- }
上面就是返回图片流的方式;
记录下!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。