您好,登錄后才能下訂單哦!
如何在Spring Boot項目中實現一個文件上傳功能?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
一、配置OSS
首先,你需要注冊阿里云的賬號并開通對象存儲服務。在準備工作完成之后,需要導入 JAVA 版本的 SDK,這里使用 maven 進行導入
<!-- 阿里云OSS對象存儲 --> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.8.0</version> </dependency>
導入完成后在 application.properties
配置文件中添加以下內容
# 節點域名 aliyun.oss.endpoint=oss-cn-xxxxxxx.aliyuncs.com # 賬戶id aliyun.oss.accessKeyId=xxxxxxxxxxxxx # 賬戶密碼 aliyun.oss.accessKeySecret=xxxxxxxxxxxxx # bucket名稱 aliyun.oss.bucketName=xxxxxxxxxxx # 簽名過期時間 aliyun.oss.policy.expire=300 # 上傳文件的最大尺寸 aliyun.oss.maxSize=10 # 上傳地址的前綴 aliyun.oss.dir.prefix=xxx # 回調參數的請求地址 aliyun.oss.callback=http://www.xxxxxx.com/api/aliyun/oss/callback
以上內容在開通服務后均可獲取到,請根據實際情況進行修改
OSSClient是OSS的Java客戶端,用于管理存儲空間和文件等OSS資源。使用Java SDK發起OSS請求,您需要初始化一個OSSClient實例,并根據需要修改ClientConfiguration的默認配置項。
根據官方文檔的描述,需要初始化一個ossClient
實例并將其注入到Spring容器中,因此可以編寫一個配置類OssConfig
@Configuration @PropertySource(value = {"classpath:application.properties"}, encoding = "utf-8") public class OssConfig { @Value("${aliyun.oss.endpoint}") private String endpoint; @Value("${aliyun.oss.accessKeyId}") private String accessKeyId; @Value("${aliyun.oss.accessKeySecret}") private String secretAccessKey; @Bean public OSS ossClient(){ return new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey); } }
更多詳細的配置,請參考官方文檔:初始化
我們以典型的表單上傳為例,在使用對象存儲OSS后,表單上傳分為以下幾個流程:
注:Policy表單域用于驗證請求的合法性。例如可以指定上傳的大小,可以指定上傳的Object名稱等,上傳成功后客戶端跳轉到的URL,上傳成功后客戶端收到的狀態碼。
PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, DIR_PREFIX); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8); // 將Policy字符串進行base64編碼 String policy = BinaryUtil.toBase64String(binaryData); // 用OSS的AccessKeySecret對base64編碼后的Policy進行簽名 String signature = ossClient.calculatePostSignature(postPolicy);
前端向OSS服務器上傳文件時要上傳Policy表單域,OSS服務器將對Policy表單域的內容進行驗證。關于 Post Policy 的詳細內容,請參考官方文檔:Post Policy
當文件上傳成功后,OSS服務器會向應用服務器發起回調請求,具體流程如下:
用戶只需要在發送給 OSS 的請求中攜帶相應的 Callback 參數,即能實現回調。
Callback 參數是由一段經過 base64 編碼的 JSON 字符串(字段)。構建 callback 參數的關鍵是指定請求回調的服務器 URL(callbackUrl)以及回調的內容(callbackBody)。
// 上傳回調參數 Callback callback = new Callback(); // 指定請求回調的服務器URL callback.setCallbackUrl(CALLBACK); //(可選)設置回調請求消息頭中Host的值,即您的服務器配置Host的值。 // callback.setCallbackHost("yourCallbackHost"); // 設置發起回調時請求body的值。 callback.setCallbackBody("{\\\"filename\\\":${object},\\\"mineType\\\":${mimeType}}"); // 設置發起回調請求的Content-Type。 callback.setCalbackBodyType(Callback.CalbackBodyType.JSON); // 設置發起回調請求的自定義參數,由Key和Value組成,Key必須以x:開始。 // callback.addCallbackVar("x:dir", "value");
更詳細的內容請閱讀官方文檔:Callback
首先編寫 Post Policy 封裝對象OssPolicyResult
@Data public class OssPolicyResult { @ApiModelProperty("用戶id") private String accessKeyId; @ApiModelProperty("Post Policy經過base64編碼過的字符串") private String policy; @ApiModelProperty("對policy簽名后的字符串") private String signature; // @ApiModelProperty("對象的鍵值") // private String key; @ApiModelProperty("上傳文件夾路徑前綴") private String dir; @ApiModelProperty("oss對外服務的訪問域名") private String host; @ApiModelProperty("上傳成功后的回調設置") private String callback; }
然后需自定義一個回調結果對象OssCallBackResult
@Data public class OssCallBackResult { @ApiModelProperty("文件的鏈接") private String url; @ApiModelProperty("文件名稱") private String filename; @ApiModelProperty("文件大小") private String size; @ApiModelProperty("文件的mimeType") private String mimeType; @ApiModelProperty("圖片文件的寬") private String width; @ApiModelProperty("圖片文件的高") private String height; }
注:以上內容可根據實際需要進行修改
之后編寫 Service 接口及實現類
Service 接口:
public interface OssService { // 生成Post Policy OssPolicyResult policy(); // 上傳成功后的回調 OssCallBackResult callback(Map<String, Object> requestBody); }
Service 實現類:
@Slf4j @Service @PropertySource(value = {"classpath:application.properties"}, encoding = "utf-8") public class OssServiceImpl implements OssService { @Value("${aliyun.oss.endpoint}") private String ENDPOINT; @Value("${aliyun.oss.accessKeyId}") private String ACCESS_KEY_ID; @Value("${aliyun.oss.accessKeySecret}") private String SECRET_ACCESS_KEY; @Value("${aliyun.oss.bucketName}") private String BUCKET_NAME; @Value("${aliyun.oss.policy.expire}") private int EXPIRE; @Value("${aliyun.oss.maxSize}") private int MAX_SIZE; @Value("${aliyun.oss.dir.prefix}") private String DIR_PREFIX; @Value("${aliyun.oss.callback}") private String CALLBACK; @Autowired private OSS ossClient; @Override public OssPolicyResult policy() { OssPolicyResult result = new OssPolicyResult(); // 簽名有效期 long expireEndTime = System.currentTimeMillis() + EXPIRE * 1000; Date expiration = new Date(expireEndTime); // 文件名稱 // String filename = UUID.randomUUID().toString(); // 文件大小 long maxSize = MAX_SIZE * 1024 * 1024; // 提交節點 String action = "http://" + BUCKET_NAME + "." + ENDPOINT; // 上傳回調參數 Callback callback = new Callback(); // 指定請求回調的服務器URL callback.setCallbackUrl(CALLBACK); //(可選)設置回調請求消息頭中Host的值,即您的服務器配置Host的值。 // callback.setCallbackHost("yourCallbackHost"); // 設置發起回調時請求body的值。 callback.setCallbackBody("{\\\"filename\\\":${object}}"); // 設置發起回調請求的Content-Type。 callback.setCalbackBodyType(Callback.CalbackBodyType.JSON); // 設置發起回調請求的自定義參數,由Key和Value組成,Key必須以x:開始。 // callback.addCallbackVar("x:dir", "value"); try { PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, DIR_PREFIX); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8); // 將Policy字符串進行base64編碼 String policy = BinaryUtil.toBase64String(binaryData); // 用OSS的AccessKeySecret對base64編碼后的Policy進行簽名 String signature = ossClient.calculatePostSignature(postPolicy); // 將callback配置進行base64編碼 String callbackData = BinaryUtil.toBase64String(OSSUtils.jsonizeCallback(callback).getBytes()); // 返回結果 result.setAccessKeyId(ACCESS_KEY_ID); result.setPolicy(policy); result.setSignature(signature); // result.setKey(filename); result.setDir(dir); result.setHost(action); result.setCallback(callbackData); } catch (Exception e) { log.error("簽名生成失敗", e); } return result; } @Override public OssCallBackResult callback(Map<String, Object> requestBody) { OssCallBackResult ossCallbackResult = new OssCallBackResult(); // 文件名 String filename = requestBody.get("filename").toString(); // 文件鏈接 String url = "https://" + BUCKET_NAME + "." + ENDPOINT + "/" + DIR_PREFIX + "/" + filename; ossCallbackResult.setUrl(url); return ossCallbackResult; } }
添加 Controller 層:
@Api(tags = "阿里云對象存儲接口") @RequestMapping("/api") @RestController public class OssController { @Autowired private OssService ossService; @ApiOperation(value = "OSS上傳簽名生成") @GetMapping("/aliyun/oss/policy") public Object policy() { return ossService.policy(); } @ApiOperation(value = "OSS上傳成功回調") @PostMapping("/aliyun/oss/callback") public Object callback(@RequestBody Map<String, Object> requestBody) { return ossService.callback(requestBody); } }
關于如何在Spring Boot項目中實現一個文件上傳功能問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。