寫在前面:
還記得首次在第一家實習機關,項目中用到了檔案上傳下載下傳。騰哥說用OSS,接着便問我有沒有使用過阿裡雲的OSS服務。當時一臉懵,啥是OSS服務??它能幹啥??怎麼用??之前總感覺一個系統中要是沒有檔案上傳下載下傳功能就稱不上是一個系統。到現在為止,所做過的業務中更是不可或缺。使用阿裡雲OSS服務,大大減輕了開發壓力,稍加配置便能輕松上手。既然用的這麼頻繁,那就記錄一下咯。
1.開通阿裡雲OSS服務
https://common-buy.aliyun.com/?spm=5176.208357.1107607.10.5e73390fav1TpM&commodityCode=ossbag&request=%7B%22region%22%3A%22china-common%22%7D#/buy
主要還是為了示範以及學習,是以就按照價格最便宜的來吧~
2.建立存儲空間
購買成功,進入OSS控制台。
在Bucket清單右側選擇,建立Bucket(存儲空間)
建立成功。則會在左側“我的通路路徑”中就能看到剛才自己建立的Bucket。
建立一個通路控制的RAM賬号和密碼
填寫完整,輸入手機驗證碼。會得到accessKeyId和accessKeySecret。記得儲存,隻會此時展示一次,想在得到就擷取不到了。
3.上傳檔案
利用OSSJava SDK來上傳檔案。
1.配置pom.xml
com.aliyun.oss aliyun-sdk-oss 2.8.3
2. 配置application.yml
#存儲本地upload: path: F://#下載下傳本地downLoad: path: G://#OSS服務entFile: endpoint: http://oss-cn-hangzhou.aliyuncs.com accessKeyId: XXXXXXXXXX accessKeySecret: YYYYYYYYY bucketName: tianhong-bucket #通路(下載下傳)請求頭 access: http://tianhong-bucket.oss-cn-hangzhou.aliyuncs.com/
accessKeyId& accessKeySecret:通路控制的RAM賬号和密碼
EndPoint(地域節點):在建立Bucket時選擇的區域對應的便是杭州節點(華東1(杭州))
Access:通路域名帶上檔案路徑,即可通過網際網路通路到 Bucket 内的任意檔案。
Ps:我這裡将Bucket ACL設定為了公共讀。若是私有,則需要在Header或Url中包含簽名。
3.GlobalConfig擷取配置檔案中OSS屬性資訊
//===================阿裡雲OSS配置[email protected]("${entFile.endpoint}")private String entFileEndpoint;@Value("${entFile.accessKeyId}")private String entFileAccessKeyId;@Value("${entFile.accessKeySecret}")private String entFileAccessKeySecret;@Value("${entFile.bucketName}")private String entFileBucketName;@Value("${entFile.access}")private String entFileAccess;//===================上傳、下載下傳位址[email protected]("${upload.path}")private String uploadPath;@Value("${downLoad.path}")private String downLoadPath;//=====================阿裡雲OSS配置=================public static String ENDPOINT;public static String ACCESS_KEY_ID;public static String ACCESS_KEY_SECRET;public static String BUCKET_NAME;public static String ACCESS;//===================上傳、下載下傳位址===================public static String UPLOAD_PATH;public static String DOWNLOAD_PATH;@Overridepublic void afterPropertiesSet() throws Exception { //======阿裡雲OSS配置========= ENDPOINT = entFileEndpoint; ACCESS_KEY_ID = entFileAccessKeyId; ACCESS_KEY_SECRET = entFileAccessKeySecret; BUCKET_NAME = entFileBucketName; ACCESS = entFileAccess; //======上傳、下載下傳位址========= UPLOAD_PATH = uploadPath; DOWNLOAD_PATH = downLoadPath;}
4.OssService做成一個Service友善後期進行對其調用
public interface OssService { //檔案上傳 String uploadFile(File file);}
5.OssServiceImpl參考API實作其内部邏輯
主要是根據配置檔案中OSS一些屬性,建立存儲空間。先判斷存儲空間是否存在,不存在則建立。接着便建立檔案路徑及檔案名稱。最後,上傳檔案到指定的存儲空間(bucketName)并将其儲存為指定的檔案名稱(objectName)。
@[email protected]("ossService")public class OssServiceImpl implements OssService { //檔案上傳 @Override public String uploadFile(File file) { String endpoint = GlobalConfig.ENDPOINT; String accessKeyId = GlobalConfig.ACCESS_KEY_ID; String accessKeySecret = GlobalConfig.ACCESS_KEY_SECRET; String bucketName = GlobalConfig.BUCKET_NAME; log.info("=========>OSS檔案上傳開始:" + file.getName()); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); String dateStr = simpleDateFormat.format(new Date()); if (null == file) { return null; } OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); try { //容器不存在,就建立 if (!ossClient.doesBucketExist(bucketName)) { ossClient.createBucket(bucketName); CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); ossClient.createBucket(createBucketRequest); } //建立檔案路徑 String fileUrl = bucketName + "/" + (dateStr + "/" + UUID.randomUUID().toString().replace("-", "") + "-" + file.getName()); //上傳檔案 PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, file)); //設定權限 這裡是公開讀 ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead); if (null != result) { log.info("==========>OSS檔案上傳成功,OSS位址:-------------------------" + fileUrl); return fileUrl; } } catch (OSSException oe) { log.error(oe.getMessage()); } catch (ClientException ce) { log.error(ce.getMessage()); } finally { //關閉 ossClient.shutdown(); } return null; }}
6. 舉例說明
做一個檔案上傳的Controller。上傳一個檔案。
@RequestMapping("/oss")@RestControllerpublic class OssController { @Value("${upload.path}") private String uploadPath; @Value("${downLoad.path}") private String downLoadPath; @Autowired private OssService ossService; //檔案上傳 @PostMapping("/upload") public WebResponse upload(MultipartFile file) throws IOException { File fileLocal = new File(uploadPath, UUID.randomUUID().toString().substring(0, 6) + "-" + file.getOriginalFilename()); //将建好的檔案用流的形式讀寫進去 并會下載下傳一份到本地 FileUtils.copyInputStreamToFile(file.getInputStream(), fileLocal); String ossUrl = ossService.uploadFile(fileLocal); return WebResponse.resSuccess("上傳成功", GlobalConfig.ACCESS + ossUrl); }}
Postman模拟檔案上傳。"key":"Content-Type","value":"multipart/form-data"
上傳成功,傳回了檔案OSS的位址。
OSS控制台檢視,檔案已經上傳成功。
4.下載下傳檔案
根據上傳成功傳回的ossUrl位址進行檔案下載下傳。注意:前面通路的access: http://tianhong-bucket.oss-cn-hangzhou.aliyuncs.com/不用傳入。隻需後面的tianhong-bucket/2020-07-03/12e7b00c21e14ebf9bf5b16a427359e6-655c82-timg.jpg具體檔案路徑即可。
@GetMapping("/downLoad")public void downloadByUrl(HttpServletRequest request, String ossUrl, HttpServletResponse response) throws Exception { if (null != ossUrl) { String fileTitle = ossUrl.substring(ossUrl.lastIndexOf("/") + 1, ossUrl.length()); fileTitle = fileTitle.substring(fileTitle.indexOf("-")+1,fileTitle.length()); String fileTitleDownName = ossUrl.substring(ossUrl.lastIndexOf("-") + 1, ossUrl.length()); //從oss讀取檔案 OSSClient ossClient = new OSSClient(GlobalConfig.ENDPOINT, GlobalConfig.ACCESS_KEY_ID, GlobalConfig.ACCESS_KEY_SECRET); // 下載下傳OSS檔案到本地檔案。如果指定的本地檔案存在會覆寫,不存在則建立。 ossClient.getObject(new GetObjectRequest(GlobalConfig.BUCKET_NAME,ossUrl),new File(downLoadPath+fileTitleDownName)); //臨時檔案下載下傳 File file = new File(GlobalConfig.UPLOAD_PATH + fileTitle); FileInputStream stream = new FileInputStream(file); response.setCharacterEncoding("utf-8"); response.setContentType("multipart/form-data"); String name = null; String agent = request.getHeader("User-Agent").toLowerCase(); if (agent.contains("msie") || agent.contains("like gecko")) { // win10 ie edge 浏覽器 和其他系統的ie name = URLEncoder.encode(fileTitleDownName, "UTF-8"); } else { // fe name = new String(fileTitleDownName.getBytes("UTF-8"), "iso-8859-1"); } response.setHeader("Content-Disposition", "attachment; filename=" + name); OutputStream os = response.getOutputStream(); byte[] b = new byte[2048]; int length; while ((length = stream.read(b)) > 0) { os.write(b, 0, length); } //關掉輸出流,否則檔案無法删除 stream.close(); os.flush(); os.close(); //删除上傳時 儲存在F盤的源檔案 file.delete(); }}
下載下傳成功。