SpringBoot實戰電商項目mall(20k+star)地址: https://github.com/macrozheng/mall
本文主要講解mall整合OSS實現文件上傳的過程,採用的是服務端簽名後前端直傳的方式。html
阿里雲對象存儲服務(Object Storage Service,簡稱 OSS),是阿里雲提供的海量、安全、低成本、高可靠的雲存儲服務。OSS可用於圖片、音視頻、日誌等海量文件的存儲。各類終端設備、Web網站程序、移動應用能夠直接向OSS寫入或讀取數據。
因爲瀏覽器處於安全考慮,不容許跨域資源訪問,因此咱們要設置OSS的跨域資源共享。
<!-- OSS SDK 相關依賴 --> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>2.5.0</version> </dependency>
修改application.yml文件,添加OSS相關配置。
注意:endpoint、accessKeyId、accessKeySecret、bucketName、callback、prefix都要改成你本身賬號OSS相關的,callback須要是公網能夠訪問的地址。前端
# OSS相關配置信息 aliyun: oss: endpoint: oss-cn-shenzhen.aliyuncs.com # oss對外服務的訪問域名 accessKeyId: test # 訪問身份驗證中用到用戶標識 accessKeySecret: test # 用戶用於加密簽名字符串和oss用來驗證簽名字符串的密鑰 bucketName: macro-oss # oss的存儲空間 policy: expire: 300 # 簽名有效期(S) maxSize: 10 # 上傳文件大小(M) callback: http://localhost:8080/aliyun/oss/callback # 文件上傳成功後的回調地址 dir: prefix: mall/images/ # 上傳文件夾路徑前綴
用於配置OSS的鏈接客戶端OSSClient。
package com.macro.mall.tiny.config; import com.aliyun.oss.OSSClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Created by macro on 2018/5/17. */ @Configuration public class OssConfig { @Value("${aliyun.oss.endpoint}") private String ALIYUN_OSS_ENDPOINT; @Value("${aliyun.oss.accessKeyId}") private String ALIYUN_OSS_ACCESSKEYID; @Value("${aliyun.oss.accessKeySecret}") private String ALIYUN_OSS_ACCESSKEYSECRET; @Bean public OSSClient ossClient(){ return new OSSClient(ALIYUN_OSS_ENDPOINT,ALIYUN_OSS_ACCESSKEYID,ALIYUN_OSS_ACCESSKEYSECRET); } }
前端直接上傳文件時所需參數,從後端返回過來。
package com.macro.mall.tiny.dto; import io.swagger.annotations.ApiModelProperty; /** * 獲取OSS上傳文件受權返回結果 * Created by macro on 2018/5/17. */ public class OssPolicyResult { @ApiModelProperty("訪問身份驗證中用到用戶標識") private String accessKeyId; @ApiModelProperty("用戶表單上傳的策略,通過base64編碼過的字符串") private String policy; @ApiModelProperty("對policy簽名後的字符串") private String signature; @ApiModelProperty("上傳文件夾路徑前綴") private String dir; @ApiModelProperty("oss對外服務的訪問域名") private String host; @ApiModelProperty("上傳成功後的回調設置") private String callback; //省略了全部getter,setter方法 }
當OSS上傳成功後,會根據該配置參數來回調對應接口。
package com.macro.mall.tiny.dto; import io.swagger.annotations.ApiModelProperty; /** * oss上傳成功後的回調參數 * Created by macro on 2018/5/17. */ public class OssCallbackParam { @ApiModelProperty("請求的回調地址") private String callbackUrl; @ApiModelProperty("回調是傳入request中的參數") private String callbackBody; @ApiModelProperty("回調時傳入參數的格式,好比表單提交形式") private String callbackBodyType; //省略了全部getter,setter方法 }
回調接口中返回的數據對象,封裝了上傳文件的信息。
package com.macro.mall.tiny.dto; import io.swagger.annotations.ApiModelProperty; /** * oss上傳文件的回調結果 * Created by macro on 2018/5/17. */ public class OssCallbackResult { @ApiModelProperty("文件名稱") private String filename; @ApiModelProperty("文件大小") private String size; @ApiModelProperty("文件的mimeType") private String mimeType; @ApiModelProperty("圖片文件的寬") private String width; @ApiModelProperty("圖片文件的高") private String height; //省略了全部getter,setter方法 }
package com.macro.mall.tiny.service; import com.macro.mall.tiny.dto.OssCallbackResult; import com.macro.mall.tiny.dto.OssPolicyResult; import javax.servlet.http.HttpServletRequest; /** * oss上傳管理Service * Created by macro on 2018/5/17. */ public interface OssService { /** * oss上傳策略生成 */ OssPolicyResult policy(); /** * oss上傳成功回調 */ OssCallbackResult callback(HttpServletRequest request); }
package com.macro.mall.tiny.service.impl; import cn.hutool.json.JSONUtil; import com.aliyun.oss.OSSClient; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.model.MatchMode; import com.aliyun.oss.model.PolicyConditions; import com.macro.mall.tiny.dto.OssCallbackParam; import com.macro.mall.tiny.dto.OssCallbackResult; import com.macro.mall.tiny.dto.OssPolicyResult; import com.macro.mall.tiny.service.OssService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; import java.util.Date; /** * oss上傳管理Service實現類 * Created by macro on 2018/5/17. */ @Service public class OssServiceImpl implements OssService { private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class); @Value("${aliyun.oss.policy.expire}") private int ALIYUN_OSS_EXPIRE; @Value("${aliyun.oss.maxSize}") private int ALIYUN_OSS_MAX_SIZE; @Value("${aliyun.oss.callback}") private String ALIYUN_OSS_CALLBACK; @Value("${aliyun.oss.bucketName}") private String ALIYUN_OSS_BUCKET_NAME; @Value("${aliyun.oss.endpoint}") private String ALIYUN_OSS_ENDPOINT; @Value("${aliyun.oss.dir.prefix}") private String ALIYUN_OSS_DIR_PREFIX; @Autowired private OSSClient ossClient; /** * 簽名生成 */ @Override public OssPolicyResult policy() { OssPolicyResult result = new OssPolicyResult(); // 存儲目錄 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String dir = ALIYUN_OSS_DIR_PREFIX+sdf.format(new Date()); // 簽名有效期 long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000; Date expiration = new Date(expireEndTime); // 文件大小 long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024; // 回調 OssCallbackParam callback = new OssCallbackParam(); callback.setCallbackUrl(ALIYUN_OSS_CALLBACK); callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"); callback.setCallbackBodyType("application/x-www-form-urlencoded"); // 提交節點 String action = "http://" + ALIYUN_OSS_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT; try { PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes("utf-8"); String policy = BinaryUtil.toBase64String(binaryData); String signature = ossClient.calculatePostSignature(postPolicy); String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes("utf-8")); // 返回結果 result.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId()); result.setPolicy(policy); result.setSignature(signature); result.setDir(dir); result.setCallback(callbackData); result.setHost(action); } catch (Exception e) { LOGGER.error("簽名生成失敗", e); } return result; } @Override public OssCallbackResult callback(HttpServletRequest request) { OssCallbackResult result= new OssCallbackResult(); String filename = request.getParameter("filename"); filename = "http://".concat(ALIYUN_OSS_BUCKET_NAME).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename); result.setFilename(filename); result.setSize(request.getParameter("size")); result.setMimeType(request.getParameter("mimeType")); result.setWidth(request.getParameter("width")); result.setHeight(request.getParameter("height")); return result; } }
package com.macro.mall.tiny.controller; import com.macro.mall.tiny.common.api.CommonResult; import com.macro.mall.tiny.dto.OssCallbackResult; import com.macro.mall.tiny.dto.OssPolicyResult; import com.macro.mall.tiny.service.impl.OssServiceImpl; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; /** * Oss相關操做接口 * Created by macro on 2018/4/26. */ @Controller @Api(tags = "OssController", description = "Oss管理") @RequestMapping("/aliyun/oss") public class OssController { @Autowired private OssServiceImpl ossService; @ApiOperation(value = "oss上傳簽名生成") @RequestMapping(value = "/policy", method = RequestMethod.GET) @ResponseBody public CommonResult<OssPolicyResult> policy() { OssPolicyResult result = ossService.policy(); return CommonResult.success(result); } @ApiOperation(value = "oss上傳成功回調") @RequestMapping(value = "callback", method = RequestMethod.POST) @ResponseBody public CommonResult<OssCallbackResult> callback(HttpServletRequest request) { OssCallbackResult ossCallbackResult = ossService.callback(request); return CommonResult.success(ossCallbackResult); } }
https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-09java
mall項目全套學習教程連載中,關注公衆號第一時間獲取。git