保姆級SpringBoot+Vue圖片上傳到阿里雲OSS教程

小二是新來的實習生,作爲技術 leader,我給他安排了一個非常簡單的練手任務,把前端 markdown 編輯器裏上傳的圖片保存到服務器端,結果他真的就把圖片直接保存到了服務器上,這下可把我氣壞了,就不能搞個對象存儲服務,比如說 OSS、MinIO?

他理直氣壯地反駁道:“誰讓你不講清楚,我去找老闆把你開掉!”我瞬間就慫了,說,“來來來,我手把手教你怎麼把圖片保存到 OSS 上,好不好?”

“不用了,還是我來教你吧。”小二非常自信,下面是他在 Spring Boot 應用中整合 OSS 做的記錄。

特此聲明:阿里雲 OSS 的產品負責人看到後請自覺過來結算下推廣費用(狗頭)。真心講:Spring Boot+OSS 在實際開發中挺常見的。

一、開通 OSS

OSS 也就是 Object Storage Service,是阿里雲提供的一套對象存儲服務,國內的競品還有七牛雲的 Kodo和騰訊雲的COS。

第一步,登錄阿里雲官網,搜索“OSS”關鍵字,進入 OSS 產品頁。

第二步,如果是 OSS 新用戶的話,可以享受 6 個月的新人專享優惠價,不過續費的時候還是會肉疼。

第三步,進入 OSS 管理控制檯,點擊「Bucket 列表」,點擊「創建 Bucket」。

Bucket 的詞面意思是桶,這裏指存儲空間,就是用於存儲對象的容器。注意讀寫權限爲“公共讀”,也就是允許互聯網用戶訪問雲空間上的圖片。

第四步,點擊「確定」就算是開通成功了。

二、整合 OSS

第一步,在 pom.xml 文件中添加 OSS 的依賴。

<!-- 阿里雲 OSS -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>

第二步,在 application.yml 文件中添加 OSS 配置項。

aliyun:
  oss:
      # oss對外服務的訪問域名
    endpoint: oss-cn-beijing.aliyuncs.com
      # 訪問身份驗證中用到用戶標識
    accessKeyId: LTAI5
      # 用戶用於加密簽名字符串和oss用來驗證簽名字符串的密鑰
    accessKeySecret: RYN
      # oss的存儲空間
    bucketName: itwanger-oss1
      # 上傳文件大小(M)
    maxSize: 3
      # 上傳文件夾路徑前綴
    dir:
      prefix: codingmore/images/

第三步,新增 OssClientConfig.java 配置類,主要就是通過 @Value 註解從配置文件中獲取配置項,然後創建 OSSClient。

@Configuration
public class OssClientConfig {
    @Value("${aliyun.oss.endpoint}")
    String endpoint ;
    @Value("${aliyun.oss.accessKeyId}")
    String accessKeyId ;
    @Value("${aliyun.oss.accessKeySecret}")
    String accessKeySecret;

    @Bean
    public OSSClient createOssClient() {
        return (OSSClient)new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
}

第四步,新增文件上傳接口 OssController.java,參數爲 MultipartFile。

@Controller
@Api(tags = "上傳")
@RequestMapping("/ossController")
public class OssController {
    @Autowired
    private IOssService ossService;

    @RequestMapping(value = "/upload",method=RequestMethod.POST)
    @ResponseBody
    @ApiOperation("上傳")
    public ResultObject<String> upload(@RequestParam("file") MultipartFile file, HttpServletRequest req)  {
        return ResultObject.success(ossService.upload(file));
    }
}

第五步,新增 Service,將文件上傳到 OSS,並返回文件保存路徑。

@Service
public class OssServiceImpl implements IOssService{

    @Value("${aliyun.oss.maxSize}")
    private int maxSize;
   
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
  
    @Value("${aliyun.oss.dir.prefix}")
    private String dirPrefix;
    
    @Autowired
    private OSSClient ossClient;   
    @Override
    public String upload(MultipartFile file) {
        try {
            return upload(file.getInputStream(), file.getOriginalFilename());
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
        }
        return null;
    }

    @Override
    public String upload(InputStream inputStream,String name) {
        String objectName = getBucketName(name);
        // 創建PutObject請求。
        ossClient.putObject(bucketName, objectName, inputStream);
        return formatPath(objectName);
    }
    private String getBucketName(String url){
        String ext = "";
        for(String extItem:imageExtension){
            if(url.indexOf(extItem) != -1){
                ext = extItem;
                break;
            }
        }
        return dirPrefix+ DateUtil.today()+"/"+ IdUtil.randomUUID()+ext;
    }

    private String formatPath(String objectName){
        return "https://"  +bucketName+"."+ ossClient.getEndpoint().getHost() + "/" + objectName;
    }
}  

第六步,打開 Apipost,測試 OSS 上傳接口,注意參數選擇文件,點擊發送後可以看到服務器端返回的圖片鏈接。

第七步,進入阿里雲 OSS 後臺管理,可以確認圖片確實已經上傳成功。

三、拉取前端代碼來測試 OSS 上傳接口

codingmore-admin-web 是編程喵(Codingmore)的前端管理項目,可以通過下面的地址拉取到本地。

https://github.com/itwanger/codingmore-admin-web

執行 yarn run dev 命令後就可以啓動 Web 管理端了,進入到文章編輯頁面,選擇一張圖片進行上傳,可以確認圖片是可以正常從前端上傳到服務器端,服務器端再上傳到 OSS,之後再返回前端圖片訪問鏈接的。

四、利用 OSS 進行自動轉鏈

第一步,在 PostsServiceImpl.java 中添加圖片轉鏈的方法,主要利用正則表達式找出文章內容中的外鏈,然後將外鏈的圖片上傳到 OSS,然後再替換掉原來的外鏈圖片。

// 匹配圖片的 markdown 語法
// ![](hhhx.png)
// ![xx](hhhx.png?ax)
public static final String IMG_PATTERN = "\\!\\[.*\\]\\((.*)\\)";

private void handleContentImg(Posts posts) {
    String content = posts.getPostContent();

    Pattern p = Pattern.compile(IMG_PATTERN, Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(content);

    Map<String, Future<String>> map = new HashMap<>();

    while (m.find()) {
        String imageTag = m.group();
        LOGGER.info("使用分組進行替換{}", imageTag);

        String imageUrl = imageTag.substring(imageTag.indexOf("(") + 1, imageTag.indexOf(")"));

        // 確認是本站鏈接,不處理
        if (imageUrl.indexOf(iOssService.getEndPoint()) != -1) {
            continue;
        }

        // 通過線程池將圖片上傳到 OSS
        Future<String> future = ossUploadImageExecutor.submit(() -> {
            return iOssService.upload(imageUrl);
        });
        map.put(imageUrl, future);
    }

    for (String oldUrl : map.keySet()) {
        Future<String> future = map.get(oldUrl);

        try {
           String imageUrl = future.get();
           content = content.replace(oldUrl, imageUrl);
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("獲取圖片鏈接出錯{}", e.getMessage());
        }
        
    }
    posts.setPostContent(content);
} 

第二步,在 OssServiceImpl.java 中添加根據外鏈地址上傳圖片到 OSS 的方法。

public String upload(String url) {
    String objectName = getFileName(url);
    try (InputStream inputStream = new URL(url).openStream()) {
        ossClient.putObject(bucketName, objectName, inputStream);
    } catch (IOException e) {
        LOGGER.error(e.getMessage());
    }
    return formatOSSPath(objectName);
}

第三步,通過 Web 管理端來測試外鏈是否轉鏈成功。先找兩張外鏈的圖片,可以看到 markdown 在預覽的時候就不顯示。

然後我們點擊發布,可以看到兩張圖片都正常顯示了,因爲轉成了 OSS 的圖片訪問地址。

五、小結

綜上來看,實習生小二在 Spring Boot 中整合 OSS 的代碼還是挺靠譜的。也許 OSS+CDN 纔是圖牀的最好解決方案,不過阿里雲的 HTTPS CDN 在 GitHub 上無法回源導致圖片不顯示的問題仍然沒有得到有效的解決。

需要源碼的小夥伴可以直接到編程喵🐱源碼路徑拉取:

https://github.com/itwanger/coding-more


本篇已收錄至 GitHub 上星標 1.8k+ star 的開源專欄《Java 程序員進階之路》,據說每一個優秀的 Java 程序員都喜歡她,風趣幽默、通俗易懂。內容包括 Java 基礎、Java 併發編程、Java 虛擬機、Java 企業級開發、Java 面試等核心知識點。學 Java,就認準 Java 程序員進階之路😄。

https://github.com/itwanger/toBeBetterJavaer

star 了這個倉庫就等於你擁有了成爲了一名優秀 Java 工程師的潛力。也可以戳下面的鏈接跳轉到《Java 程序員進階之路》的官網網址,開始愉快的學習之旅吧。

https://tobebetterjavaer.com/

沒有什麼使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧靜的港灣,我是不繫之舟

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章