Java使用OSS文件Web直传并进行回调

OSS上传文件的三种模式

1.web端直传种模式

Web端常见的上传方法是用户在浏览器或app端上传文件到应用服务器,然后应用服务器再把文件上传到OSS,如下图所示:在这里插入图片描述
特点:上传慢。先上传到应用服务器,再上传到OSS

2.服务端签名后直传

采用javaScript端向服务端发起签名请求,获取参数后直传OSS
在这里插入图片描述
特点:客户端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。

3.服务端签名后直传并设置上传回调

客户端向服务端发起签名请求后,直传OSS然后OSS会回调对应的服务端回调接口,OSS回调完成后,应用服务器再返回结果给客户端。
在这里插入图片描述
特点:用户上传一个文件到OSS后,OSS会将上传结果返回给应用服务器,然后应用服务器会给OSS响应,然后OSS会将相关响应通知给客户端的用户。

后端(Java)代码案例:

1、导入阿里云的jar

	<!--    OSS    --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>2.8.3</version></dependency><!--    日志    --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.73</version></dependency><!--    json序列化反序列化    --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></dependency><!--    lombok    --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

在编写代码的时候注意导入的jar是否为此jar,本文引入的为此jar,因为阿里云的jar更新迭代的几个版本有依赖关系。

1、Controller层

@CrossOrigin
@RestController
public class OssController {@AutowiredOssService ossService;/*** 获取oss系统配置* @return*/@PostMapping("/oss/config/get")@ApiOperation("获取oss系统配置")public JsonResult<Map> getOssConfig(){try {return JsonResult.ok(ossService.generateOssParam());} catch (Exception e) {e.printStackTrace();}return null;}/*** 获取回调* @param callBackHost* @param callBackInterFace* @param callBackBody* @param callbackBodyType* @return* @throws UnsupportedEncodingException*/@PostMapping("/call/back/get")@ApiOperation("获取回调")public String generateCallBack(String callBackHost, String callBackInterFace, String callBackBody,String callbackBodyType) throws UnsupportedEncodingException {return ossService.generateCallBack(callBackHost,callBackInterFace,callBackBody,callbackBodyType);}/*** 获取签名* @param callBack 回调信息* @return*/@PostMapping("/generateSign/get")@ApiOperation("获取签名")public JsonResult<Map> generateSign(String callBack){try {return JsonResult.ok(ossService.generateSign(callBack));} catch (Exception e) {e.printStackTrace();}return null;}/*** @Description OSS上传回调* @Author* @Param [ossCallbackBody, authorization, publicKeyUrlBase64, request, response]* @Return com.ejsino.chat.config.domain.JSONResult* @return*/@PostMapping("/ossCallBack")@ApiOperation("OSS上传回调")public JsonResult<String> callBack(@RequestBody String ossCallbackBody, @RequestHeader("Authorization") String authorization,@RequestHeader("x-oss-pub-key-url") String publicKeyUrlBase64, HttpServletRequest request,HttpServletResponse response) {boolean isCallBack = ossService.verifyOSSCallbackRequest(authorization, publicKeyUrlBase64, ossCallbackBody, request.getQueryString(), request.getRequestURI());if (isCallBack) {response.setStatus(HttpServletResponse.SC_OK);// 此处必须使用json形式返回,不然oss回调报 Response body is not valid json format.return JsonResult.ok("success");} else {response.setStatus(HttpServletResponse.SC_BAD_REQUEST);// 此处必须使用json形式返回,不然oss回调报 Response body is not valid json format.return JsonResult.ok("error");}}

2、Service层

@Service
public class OssService {private Logger log = LoggerFactory.getLogger("logger");/*** @Description OSS上传需要的OSS服务参数获取* @Param []* @Return java.util.HashMap*/public HashMap<String, Object> generateOssParam() throws Exception {try {// 获取域名String domain = "<填写自己应用服务器地址>";// 文件路径String dir = "<填写oss文件路径>"; // 例如: 'mytest' 切记不要写成 '/mytest' !!!String bucketName = "";String endPoint = "";String accessKeyId = "";String host = "http://" + bucketName;HashMap<String, Object> respMap = new LinkedHashMap<String, Object>();respMap.put("accessid", accessKeyId);respMap.put("dir", dir);respMap.put("host", host);respMap.put("domain", domain);return respMap;} catch (Exception e) {log.error("获取OSS上传参数失败:" + e);throw new Exception("获取OSS上传参数失败!");}}/*** @Description OSS回调系统服务参数生成* @Param [callBackHost:要OSS进行回调的服务域名(不带http),* callBackInterFace:要进行回调的接口(oss上传结束进行请求的接口),* callBackBody:进行回调时携带的参数(以:key=value 的形式进行携带)]* @Return java.lang.String*/public String generateCallBack(String callBackHost, String callBackInterFace, String callBackBody,String callbackBodyType) throws UnsupportedEncodingException {Map<String, Object> callbackMap = new HashMap<String, Object>();callbackMap.put("callbackUrl", "http://" + callBackHost + callBackInterFace);callbackMap.put("callbackHost", callBackHost);callbackMap.put("callbackBody", callBackBody);callbackMap.put("callBackType",callbackBodyType);callbackMap.put("callbackBodyType", "application/x-www-form-urlencoded");byte[] bytes = JSON.toJSONString(callbackMap).getBytes();String callBackString = BinaryUtil.toBase64String(bytes);System.err.println(callBackString);return callBackString;}/*** @Description 生成签名* @Param [callBack :要进行回调的参数,传入为空即默认为不进行回调]* @Return java.util.HashMap*/public HashMap<String, Object> generateSign(String callBack) throws Exception {//获取上传oss需要的基本参数String endPoint = "";String accessKeyId = "";String accessKeySecret = "";String dir = "<填写oss文件路径>"; // 例如: 'mytest' 切记不要写成 '/mytest' !!!OSSClient client = null;try {//开启OSS客户端client = new OSSClient(endPoint, accessKeyId, accessKeySecret);long expireTime = 100;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;//生成的到期时间转换位s,并转换为StringString expire = String.valueOf(expireEndTime / 1000);PolicyConditions policyConditions = new PolicyConditions();policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);//根据到期时间生成policyDate expiration = new Date(expireEndTime);String postPolicy = client.generatePostPolicy(expiration, policyConditions);//生成signatureString postSignature = client.calculatePostSignature(postPolicy);//对policy进行UTF-8编码后转base64byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);//生成上传文件的文件名String fileName = "mytest" + UUID.randomUUID().toString();//封装生成好的数据进行参数返回HashMap<String, Object> respMap = new LinkedHashMap<String, Object>();respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("expire", expire);respMap.put("fileName", fileName);//callBack不为空时为OSS回调web服务上传if (callBack != null && callBack != "") {respMap.put("callback", callBack);}return respMap;} catch (Exception e) {log.error("生成OSS上传签名失败:" + e);throw new Exception("生成OSS上传签名失败!");} finally {if (client != null) {client.shutdown();}}}/*** @Description OSS回调请求验证* @Param [authorizationInput, pubKeyInput, ossCallbackBody, queryString, uri]* @Return boolean*/public boolean verifyOSSCallbackRequest(String authorizationInput, String pubKeyInput, String ossCallbackBody, String queryString, String uri){boolean ret = false;try {//将base64编码的数据进行还原byte[] authorization = BinaryUtil.fromBase64String(authorizationInput);byte[] pubKey = BinaryUtil.fromBase64String(pubKeyInput);String pubKeyAddr = new String(pubKey);if (!pubKeyAddr.startsWith("http://gosspublic.alicdn.com/") && !pubKeyAddr.startsWith("https://gosspublic.alicdn.com/")) {log.error("pub key addr must be oss address");return false;}//获取请求中的公钥信息String retString = executeGet(pubKeyAddr);retString = retString.replace("-----BEGIN PUBLIC KEY-----", "");retString = retString.replace("-----END PUBLIC KEY-----", "");String decodeUri = URLDecoder.decode(uri, "utf-8");if (queryString != null && !"".equals(queryString)) {decodeUri += "?" + queryString;}decodeUri += "\n" + ossCallbackBody;ret = doCheck(decodeUri, authorization, retString);} catch (Exception e) {ret = false;log.error("验证OSS请求出现异常:" + e);}return ret;}/*** @Description 获取请求中的参数* @Param [pubKeyUrl]* @Return java.lang.String*/@SuppressWarnings({"finally"})private String executeGet(String pubKeyUrl) throws Exception {BufferedReader in = null;String content = null;try {// 定义HttpClient@SuppressWarnings("resource")DefaultHttpClient defaultHttpClient = new DefaultHttpClient();// 实例化HTTP方法HttpGet request = new HttpGet();request.setURI(new URI(pubKeyUrl));HttpResponse response = defaultHttpClient.execute(request);in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuffer sb = new StringBuffer("");String line = "";String NL = System.getProperty("line.separator");while ((line = in.readLine()) != null) {sb.append(line + NL);}in.close();content = sb.toString();return content;} catch (Exception e) {log.error("解析公钥参数失败:" + e);throw new Exception("解析公钥参数失败!");} finally {if (in != null) {try {in.close();} catch (IOException e) {log.error("关闭BufferedReader出现异常:" + e);}}}}/*** @Description 对请求参数进行规则校验* @Param [content, sign, publicKey]* @Return boolean*/private boolean doCheck(String content, byte[] sign, String publicKey) {try {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] encodedKey = BinaryUtil.fromBase64String(publicKey);PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));java.security.Signature signature = java.security.Signature.getInstance("MD5withRSA");signature.initVerify(pubKey);signature.update(content.getBytes());boolean bverify = signature.verify(sign);return bverify;} catch (Exception e) {log.error("校验出现异常:" + e);}return false;}}

至此,Java使用OSS直传就完成啦,其中 ‘<>’ 中的值按照提示更改即可,如遇到 xml 异常可以查询 OSS对象存储错误响应


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部