oss介绍
oss是使用api存储文件的服务,是阿里云提供的一种存储服务,但是,oss的api文档特别烂,根本就无法理解,捏麻麻滴,本来我是打算采用客户端请求服务器签名后文件带着签名上传oss的直传模式,但是api文档特别烂,我已经解决了服务器下发签名,但是没有找到客户端带签名上传oss的api文档 ,于是我换了一种简单直接一点的方法,就是客户端请求服务端,将MultipartFile上传到服务器后,服务器上传到oss,也算是解决了,这种方法对服务器带宽占用很大,我这个项目没有多少并发,所以采用了这种方法。
服务器端的开发
callback.setCallbackBody(StringEscapeUtils.escapeJava(s));
这个写法是要将json的string进行一个转义,不然oss会报request错误- 在回调的接口也需要返回一个json,不能是void返回,不然oss会爆repsonse错误
pom文件
<!-- 阿里云oss的依赖sdk-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
controller
@PostMapping("/postFile/{euid}")
public R postFile(@PathVariable("euid") String euid, @RequestParam("file") MultipartFile multipartFile) {
return coverErrorService.postFileByEuid(euid, multipartFile);
}
/**
* oss上传完成的回调
*/
@PostMapping("/putoss/callback")
public R putOssCallBack(@RequestBody Map<String, String> respondBody) {
return coverErrorService.putOssCallBack(respondBody);
}
serviceImpl
@SneakyThrows
@Override
public R postFileByEuid(String euid, MultipartFile multipartFile) {
CoverErrorEntity errorByEuid = findErrorByEuid(euid);
if (errorByEuid != null) {
OSS ossClient = ossClientUtils.getOssClient();
String data = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String[] split = multipartFile.getOriginalFilename().split("\\.");
String info = String.format("%s/%s/%s.%s", data, errorByEuid.getUid(), UUID.randomUUID(), split[split.length - 1]);
//设置回调
PutObjectRequest putObjectRequest = new PutObjectRequest("cover-safety", info,
multipartFile.getInputStream());
Callback callback = new Callback();
callback.setCallbackUrl(callBackUrl);
log.info("请求链接:" + callBackUrl);
HashMap<String, String> cb = new HashMap<>();
cb.put("statue", "success");
cb.put("url", "https://cover-safety.oss-cn-hangzhou.aliyuncs.com/" + info);
cb.put("euid", errorByEuid.getUid());
String s = new ObjectMapper().writeValueAsString(cb);
callback.setCallbackBody(StringEscapeUtils.escapeJava(s));
callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);
putObjectRequest.setCallback(callback);
//上传
ossClient.putObject(putObjectRequest);
ossClient.shutdown();
} else {
return R.error().put(Constant.REASON, "没有对应的EUID");
}
return R.ok();
}
@Override
public R putOssCallBack(Map<String, String> respondBody) {
log.info("存储成功{}", respondBody);
//进行一个数据库的存储
CoverErrorEntity euid = findErrorByEuid(respondBody.get("euid"));
if (euid != null) {
//存储路径地址
UpdateWrapper<CoverErrorEntity> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("uid", euid.getUid());
euid.setErrorImage(respondBody.get("url"));
this.baseMapper.update(euid, updateWrapper);
}
return R.ok();
}
oss工具类
package com.xyxy.coversafety.coversafetywork.work.tools.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.xyxy.coversafety.coversafetywork.work.entity.CoverErrorEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @Author: PengHaiChen
* @Description:
* @Date: Create in 12:51 2021/10/15
* 在业务逻辑中,需要客户端请求服务端的签名后上传到oss,不然本地服务器载荷太大了
*/
@Component
@Slf4j
public class OssClientUtils {
@Value("${oss.endpoint}")
private String endpoint;
@Value("${oss.access-key}")
private String accessKeyId;
@Value("${oss.secret-key}")
private String accessKeySecret;
private Map<String, String> respMap;
public OSS getOssClient() {
log.info(endpoint, accessKeyId, accessKeySecret);
return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
}
public Map<String, String> generatePostPolicy(CoverErrorEntity coverErrorEntity) {
String bucket = "cover-safety"; // 请填写您的 bucketname 。
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88:8888";
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = String.format("%s/%s/", format, coverErrorEntity.getUid());// 用户上传文件时指定的前缀。
// 创建OSSClient实例。
OSS ossClient = getOssClient();
try {
long expireTime = 180;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 10485760);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
respMap = new LinkedHashMap<String, String>();
respMap.put("accessid", accessKeyId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
// respMap.put("expire", formatISO8601Date(expiration));
} catch (Exception e) {
// Assert.fail(e.getMessage());
log.info(e.getMessage());
} finally {
ossClient.shutdown();
}
return respMap;
}
}
ossyml配置
oss:
secret-key: ****
access-key: ****
endpoint: oss-cn-hangzhou.aliyuncs.com
callback-url: http://119.3.40.236:23333/work/covererror/putoss/callback