国产精品chinese,色综合天天综合精品网国产在线,成午夜免费视频在线观看,清纯女学生被强行糟蹋小说

    <td id="ojr13"><tr id="ojr13"><label id="ojr13"></label></tr></td>
        • <source id="ojr13"></source>
            <td id="ojr13"><ins id="ojr13"><label id="ojr13"></label></ins></td>

            Article / 文章中心

            怎么用springboot操作阿里云OSS實(shí)現(xiàn)文件上傳,下載,刪除(附源碼)

            發(fā)布時(shí)間:2021-12-09 點(diǎn)擊數(shù):1057
            Gartner曾在陳述中指出,未來的安全或多或少都會(huì)用到云的才能。阿里云作為全球搶先的云廠商,一向在探究借助云基礎(chǔ)設(shè)施的原生優(yōu)勢和技能盈利突破安全極限難題。目前已經(jīng)形成了覆蓋計(jì)算環(huán)境安全、主機(jī)安全、網(wǎng)絡(luò)安全、應(yīng)用安全、數(shù)據(jù)與身份安全、安全運(yùn)營與辦理六大核心范疇61個(gè)才能項(xiàng)的全體安全處理方案,概況能夠查看《Welcome on board|阿里云全體安全才能初次露臉!》。

            Springboot 去操作阿里云OSS文件存儲(chǔ)。


            1.需求

            (沒踩過下面的坑的小伙伴可以直接跳過這一章節(jié))


            問題簡述


            首先,我在之前自己做一些開源小項(xiàng)目案例中遇到一些文件上傳下載的問題,比如在本機(jī)文件上傳和下載都可以正常使用,通過將文件上傳到Springboot項(xiàng)目的根目錄下,按日期分文件夾,文件訪問也很方便,可以直接返回文件相對路徑地址,并直接可以訪問。


            問題


            然而,這種方式存在弊端,因?yàn)楫?dāng)項(xiàng)目打包(jar包)部署阿里云學(xué)生機(jī)后,出現(xiàn)類似io.NotFoundException...(No Such Directory)的問題,,而如果打war包部署到tomcat則沒問題,可以正常使用,經(jīng)過排查很久,找出問題所在:

            因?yàn)閖ar打包封裝后是不能改變其內(nèi)部目錄結(jié)構(gòu)的,也就是說,按日期分類的文件上傳文件夾,如果當(dāng)需要?jiǎng)?chuàng)建新日期的文件夾的時(shí)候,是無法在jar包中新增文件夾的,這時(shí)候就會(huì)出現(xiàn)IO異常問題。而對于放在tomcat中的war包,當(dāng)tomcat運(yùn)行的時(shí)候會(huì)自動(dòng)解壓war包,其在服務(wù)器上是存在真實(shí)路徑的。


            解決方案


            方案一:我在網(wǎng)上找了一種方法,是通過打完jar包部署后,給springboot項(xiàng)目static下的文件上傳文件夾單獨(dú)分離出來(相當(dāng)于是以相對路徑換絕對路徑),訪問的時(shí)候直接相當(dāng)通過服務(wù)器上和jar包同級目錄下新建一個(gè)文件上傳文件夾。

            方案二:直接將文件上傳到服務(wù)器指定路徑下的文件上傳位置,這種方式也相當(dāng)于直接使用絕對路徑。

            方案三:在服務(wù)器上使用FastDFS和Nginx搭建分布式文件存儲(chǔ),這種方式比較復(fù)雜,而且學(xué)生及本來內(nèi)存和帶寬就小,在自己電腦的虛擬機(jī)可以試試這種方案,還是挺好用的,學(xué)生服務(wù)器就算了。

            方案四:就是直接將文件上傳到阿里云OSS文件存儲(chǔ)系統(tǒng)上

            2. 阿里云OSS購買和配置

            這個(gè)比較簡單,給大家推薦一篇博文自己了解下阿里云oss購買和配置,也可以參考阿里云OSS官方文檔。


            3. Springboot操作OSS

            創(chuàng)建一個(gè)spring boot項(xiàng)目,pom文件需要引入依賴:


            pom.xml

            <dependencies>  <!--  個(gè)人版本踩坑:  不加這個(gè)依賴的話,當(dāng)在配置類中  使用@ConfigurationProperties(prefix = "aliyun")注解時(shí),  我這個(gè)版本的spring boot會(huì)提示有問題  -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-configuration-processor</artifactId>  <optional>true</optional>  </dependency>  <!-- swagger2 -->  <dependency>  <groupId>io.springfox</groupId>  <artifactId>springfox-swagger2</artifactId>  <version>2.9.2</version>  </dependency>  <!-- swagger ui -->  <dependency>  <groupId>io.springfox</groupId>  <artifactId>springfox-swagger-ui</artifactId>  <version>2.9.2</version>  </dependency>  <!-- thymeleaf 可不加,個(gè)人習(xí)慣性引入 -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-thymeleaf</artifactId>  </dependency>  <!-- web -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  </dependency>  <!-- 熱部署,看個(gè)人習(xí)慣 -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-devtools</artifactId>  <scope>runtime</scope>  <optional>true</optional>  </dependency>   <!-- 小辣椒插件,推薦使用,可以節(jié)省javaBean的setter/getter,還可以使用鏈?zhǔn)秸{(diào)用 -->  <dependency>  <groupId>org.projectlombok</groupId>  <artifactId>lombok</artifactId>  <optional>true</optional>  </dependency>  <!-- fastJson -->  <dependency>  <groupId>com.alibaba</groupId>  <artifactId>fastjson</artifactId>  <version>1.2.62</version>  </dependency>  <!-- aliyun-oos -->  <dependency>  <groupId>com.aliyun.oss</groupId>  <artifactId>aliyun-sdk-oss</artifactId>  <version>2.8.3</version>  </dependency>  <dependency>  <groupId>joda-time</groupId>  <artifactId>joda-time</artifactId>  <version>2.10.1</version>  </dependency>  <!-- apache-common-lang3 -->  <dependency>  <groupId>org.apache.commons</groupId>  <artifactId>commons-lang3</artifactId>  <version>3.8.1</version>  </dependency>  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  <exclusions>  <exclusion>  <groupId>org.junit.vintage</groupId>  <artifactId>junit-vintage-engine</artifactId>  </exclusion>  </exclusions>  </dependency> </dependencies> 

            image.png

            我們使用自己添加的application-aliyun-oss.properties配置文件,去配置OSS相關(guān)信息,之所以不在application.yml 中配置,看個(gè)人習(xí)慣了,因?yàn)樽远x的配置屬性還是提出來配比較好,沒必要所有的都配到application.yml(properties)中去。


            application-aliyun-oss.properties


            # 文件上傳大小限制 spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=1000MB  # 地域節(jié)點(diǎn) aliyun.endPoint=oss-cn-beijing.aliyuncs.com # Bucket 域名 aliyun.urlPrefix=http://csp-xxxx.oss-cn-beijing.aliyuncs.com/ # accessKey Id aliyun.accessKeyId=LTAI4XXXXXXXzqD1saGFZ # accessKey Secret aliyun.accessKeySecret=2WjxNXXXXXXXX4f2bREc # 你的Bucket名稱 aliyun.bucketName=csp-xxxx # 目標(biāo)文件夾 aliyun.fileHost=files 

            config包下的相關(guān)配置類

            AliyunOssConfig.java

            /**  * @Auther: csp1999  * @Date: 2020/10/31/13:33  * @Description: 阿里云 OSS 基本配置  */ // 聲明配置類,放入Spring容器 @Configuration // 指定配置文件位置 @PropertySource(value = {"classpath:application-aliyun-oss.properties"}) // 指定配置文件中自定義屬性前綴 @ConfigurationProperties(prefix = "aliyun") @Data// lombok @Accessors(chain = true)// 開啟鏈?zhǔn)秸{(diào)用 public class AliyunOssConfig {  private String endPoint;// 地域節(jié)點(diǎn)  private String accessKeyId;  private String accessKeySecret;  private String bucketName;// OSS的Bucket名稱  private String urlPrefix;// Bucket 域名  private String fileHost;// 目標(biāo)文件夾   // 將OSS 客戶端交給Spring容器托管  @Bean  public OSS OSSClient() {  return new OSSClient(endPoint, accessKeyId, accessKeySecret);  } } 

            Swagger2Config.java

            /**  * @Auther: csp1999  * @Date: 2020/10/31/16:30  * @Description: Swagger 配置類  */ @Configuration @EnableSwagger2// 開啟swagger2 public class Swagger2Config {   @Bean  public Docket webApiConfig() {   return new Docket(DocumentationType.SWAGGER_2)  .groupName("webApi")  .apiInfo(webApiInfo())  .select()  .paths(Predicates.not(PathSelectors.regex("/error.*")))  .build();  }   private ApiInfo webApiInfo() {  return new ApiInfoBuilder()  .title("SpringBoot整合OSS-API文檔")  .description("阿里云OSS-文件上傳下載測試")  .version("1.0")  .contact(new Contact("CSP", "https://blog.csdn.net/weixin_43591980", ""))  .build();  } } 

            定義一個(gè)關(guān)于執(zhí)行狀態(tài)結(jié)果的枚舉類

            /**  * @Auther: csp1999  * @Date: 2020/10/31/17:03  * @Description: 狀態(tài)碼枚舉類  */ public enum StatusCode {  SUCCESS("success",200),ERROR("error",500);  private String msg;  private Integer code;   StatusCode(String msg,Integer code){  this.msg = msg;  this.code = code;  }  StatusCode(Integer code){  this.code = code;  }  StatusCode(String msg){  this.msg = msg;  }  public String getMsg() {  return msg;  }  public void setMsg(String msg) {  this.msg = msg;  }  public Integer getCode() {  return code;  }  public void setCode(Integer code) {  this.code = code;  } } 

            service層

            在service使用ossClient操作阿里云OSS,進(jìn)行上傳、下載、刪除、查看所有文件等操作,同時(shí)可以將圖片的url進(jìn)行入庫操作:

            FileUploadService.java

            /**  * @Auther: csp1999  * @Date: 2020/10/31/14:30  * @Description: 文件上傳Service (為節(jié)省文章中的代碼篇幅,不再做接口實(shí)現(xiàn)類處理)  */ @Service("fileUploadService") public class FileUploadService {  // 允許上傳文件(圖片)的格式  private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg",  ".jpeg", ".gif", ".png"};  @Autowired  private OSS ossClient;// 注入阿里云oss文件服務(wù)器客戶端  @Autowired  private AliyunOssConfig aliyunOssConfig;// 注入阿里云OSS基本配置類   /*  * 文件上傳  * 注:阿里云OSS文件上傳官方文檔鏈接:https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.749.11987a7dRYVSzn  * @param: uploadFile  * @return: string  * @create: 2020/10/31 14:36  * @author: csp1999  */  public String upload(MultipartFile uploadFile) {  // 獲取oss的Bucket名稱  String bucketName = aliyunOssConfig.getBucketName();  // 獲取oss的地域節(jié)點(diǎn)  String endpoint = aliyunOssConfig.getEndPoint();  // 獲取oss的AccessKeySecret  String accessKeySecret = aliyunOssConfig.getAccessKeySecret();  // 獲取oss的AccessKeyId  String accessKeyId = aliyunOssConfig.getAccessKeyId();  // 獲取oss目標(biāo)文件夾  String filehost = aliyunOssConfig.getFileHost();  // 返回圖片上傳后返回的url  String returnImgeUrl = "";   // 校驗(yàn)圖片格式  boolean isLegal = false;  for (String type : IMAGE_TYPE) {  if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), type)) {  isLegal = true;  break;  }  }  if (!isLegal) {// 如果圖片格式不合法  return StatusCode.ERROR.getMsg();  }  // 獲取文件原名稱  String originalFilename = uploadFile.getOriginalFilename();  // 獲取文件類型  String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));  // 新文件名稱  String newFileName = UUID.randomUUID().toString() + fileType;  // 構(gòu)建日期路徑, 例如:OSS目標(biāo)文件夾/2020/10/31/文件名  String filePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());  // 文件上傳的路徑地址  String uploadImgeUrl = filehost + "/" + filePath + "/" + newFileName;   // 獲取文件輸入流  InputStream inputStream = null;  try {  inputStream = uploadFile.getInputStream();  } catch (IOException e) {  e.printStackTrace();  }  /**  * 下面兩行代碼是重點(diǎn)坑:  * 現(xiàn)在阿里云OSS 默認(rèn)圖片上傳ContentType是image/jpeg  * 也就是說,獲取圖片鏈接后,圖片是下載鏈接,而并非在線瀏覽鏈接,  * 因此,這里在上傳的時(shí)候要解決ContentType的問題,將其改為image/jpg  */  ObjectMetadata meta = new ObjectMetadata();  meta.setContentType("image/jpg");   //文件上傳至阿里云OSS  ossClient.putObject(bucketName, uploadImgeUrl, inputStream, meta);  /**  * 注意:在實(shí)際項(xiàng)目中,文件上傳成功后,數(shù)據(jù)庫中存儲(chǔ)文件地址  */  // 獲取文件上傳后的圖片返回地址  returnImgeUrl = "http://" + bucketName + "." + endpoint + "/" + uploadImgeUrl;   return returnImgeUrl;  }   /*  * 文件下載  * @param: fileName  * @param: outputStream  * @return: void  * @create: 2020/10/31 16:19  * @author: csp1999  */  public String download(String fileName, HttpServletResponse response) throws UnsupportedEncodingException { //        // 設(shè)置響應(yīng)頭為下載 //        response.setContentType("application/x-download"); //        // 設(shè)置下載的文件名 //        response.addHeader("Content-Disposition", "attachment;fileName=" + fileName); //        response.setCharacterEncoding("UTF-8");  // 文件名以附件的形式下載  response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));   // 獲取oss的Bucket名稱  String bucketName = aliyunOssConfig.getBucketName();  // 獲取oss目標(biāo)文件夾  String filehost = aliyunOssConfig.getFileHost();  // 日期目錄  // 注意,這里雖然寫成這種固定獲取日期目錄的形式,邏輯上確實(shí)存在問題,但是實(shí)際上,filePath的日期目錄應(yīng)該是從數(shù)據(jù)庫查詢的  String filePath = new DateTime().toString("yyyy/MM/dd");   String fileKey = filehost + "/" + filePath + "/" + fileName;  // ossObject包含文件所在的存儲(chǔ)空間名稱、文件名稱、文件元信息以及一個(gè)輸入流。  OSSObject ossObject = ossClient.getObject(bucketName, fileKey);  try {  // 讀取文件內(nèi)容。  InputStream inputStream = ossObject.getObjectContent();  BufferedInputStream in = new BufferedInputStream(inputStream);// 把輸入流放入緩存流  ServletOutputStream outputStream = response.getOutputStream();  BufferedOutputStream out = new BufferedOutputStream(outputStream);// 把輸出流放入緩存流  byte[] buffer = new byte[1024];  int len = 0;  while ((len = in.read(buffer)) != -1) {  out.write(buffer, 0, len);  }  if (out != null) {  out.flush();  out.close();  }  if (in != null) {  in.close();  }  return StatusCode.SUCCESS.getMsg();  } catch (Exception e) {  return StatusCode.ERROR.getMsg();  }  }   /*  * 文件刪除  * @param: objectName  * @return: java.lang.String  * @create: 2020/10/31 16:50  * @author: csp1999  */  public String delete(String fileName) {  // 獲取oss的Bucket名稱  String bucketName = aliyunOssConfig.getBucketName();  // 獲取oss的地域節(jié)點(diǎn)  String endpoint = aliyunOssConfig.getEndPoint();  // 獲取oss的AccessKeySecret  String accessKeySecret = aliyunOssConfig.getAccessKeySecret();  // 獲取oss的AccessKeyId  String accessKeyId = aliyunOssConfig.getAccessKeyId();  // 獲取oss目標(biāo)文件夾  String filehost = aliyunOssConfig.getFileHost();  // 日期目錄  // 注意,這里雖然寫成這種固定獲取日期目錄的形式,邏輯上確實(shí)存在問題,但是實(shí)際上,filePath的日期目錄應(yīng)該是從數(shù)據(jù)庫查詢的  String filePath = new DateTime().toString("yyyy/MM/dd");   try {  /**  * 注意:在實(shí)際項(xiàng)目中,不需要?jiǎng)h除OSS文件服務(wù)器中的文件,  * 只需要?jiǎng)h除數(shù)據(jù)庫存儲(chǔ)的文件路徑即可!  */  // 建議在方法中創(chuàng)建OSSClient 而不是使用@Bean注入,不然容易出現(xiàn)Connection pool shut down  OSSClient ossClient = new OSSClient(endpoint,  accessKeyId, accessKeySecret);  // 根據(jù)BucketName,filetName刪除文件  // 刪除目錄中的文件,如果是最后一個(gè)文件fileoath目錄會(huì)被刪除。  String fileKey = filehost + "/" + filePath + "/" + fileName;  ossClient.deleteObject(bucketName, fileKey);   try {  } finally {  ossClient.shutdown();  }  System.out.println("文件刪除!");  return StatusCode.SUCCESS.getMsg();  } catch (Exception e) {  e.printStackTrace();  return StatusCode.ERROR.getMsg();  }  } } 

            controller層

            controller提供測試接口

            /**  * @Auther: csp1999  * @Date: 2020/10/31/16:40  * @Description: OSS 文件上傳controller  */ @Api(description = "阿里云OSS文件上傳、下載、刪除API") @RequestMapping("api/pri/file") @RestController public class OssFileController {  @Autowired  private FileUploadService fileUploadService;   /*  * 文件上傳api  * @param: file  * @return: com.alibaba.fastjson.JSONObject  * @create: 2020/10/31 17:35  * @author: csp1999  */  @ApiOperation(value = "文件上傳")  @PostMapping("upload")  public JSONObject upload(@RequestParam("file") MultipartFile file) {  JSONObject jsonObject = new JSONObject();  if (file != null) {  String returnFileUrl = fileUploadService.upload(file);  if (returnFileUrl.equals("error")) {  jsonObject.put("error", "文件上傳失??!");  return jsonObject;  }  jsonObject.put("success", "文件上傳成功!");  jsonObject.put("returnFileUrl", returnFileUrl);  return jsonObject;  } else {  jsonObject.put("error", "文件上傳失?。?);  return jsonObject;  }  }   /*  * 文件下載api  * @param: fileName  * @param: response  * @return: com.alibaba.fastjson.JSONObject  * @create: 2020/10/31 17:35  * @author: csp1999  */  @ApiOperation(value = "文件下載")  @GetMapping(value = "download/{fileName}")  public JSONObject download(@PathVariable("fileName") String fileName, HttpServletResponse response) throws Exception {  JSONObject jsonObject = new JSONObject();   String status = fileUploadService.download(fileName, response);  if (status.equals("error")) {  jsonObject.put("error", "文件下載失??!");  return jsonObject;  } else {  jsonObject.put("success", "文件下載成功!");  return jsonObject;  }  }   /*  * 文件刪除api  * @param: fileName  * @return: com.alibaba.fastjson.JSONObject  * @create: 2020/10/31 17:35  * @author: csp1999  */  @ApiOperation(value = "文件刪除")  @GetMapping("/delete/{fileName}")  public JSONObject DeleteFile(@PathVariable("fileName") String fileName) {  JSONObject jsonObject = new JSONObject();   String status = fileUploadService.delete(fileName);  if (status.equals("error")) {  jsonObject.put("error", "文件刪除失?。?);  return jsonObject;  } else {  jsonObject.put("success", "文件刪除成功!");  return jsonObject;  }  } } 


            4.運(yùn)行項(xiàng)目測試API接口

            本機(jī)訪問:http://localhost:8083/swagger-ui.html

            image.png

            image.png

            image.png