5

SpringBoot 整合阿里云OSS文件上传、下载、查看、删除

 2 years ago
source link: https://segmentfault.com/a/1190000040035818
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

SpringBoot 整合阿里云OSS文件上传、下载、查看、删除

涉及知识点

  • OSS简介,以及阿里云OSS控制台快速入门使用
  • SpringBoot 整合 阿里云OSS存储服务,进行文件上传、下载、查看、删除
  • 阿里云OSS文档介绍,以及快速入门使用
  • lombok 入门使用以及 IDEA lombok 插件安装
  • SpringMVC 与 AJAX 前后端分离交互
  • AJAX 文件异步上传

开发前准备

  • 开发工具:IDEA
  • 基础环境:Maven + JDK8
  • 所用技术:SpringBoot、lombok、阿里云OSS存储服务
  • SpringBoot版本:2.4.5

使用阿里云OSS

1、创建Bucket

使用OSS,首先需要创建 Bucket,Bucket 翻译成中文是水桶的意思,把存储的图片资源看做是水,想要盛水必须得有桶。
进入控制台,https://oss.console.aliyun.co...
image.png
点击创建 Bucket
image.png
创建完成后,Bucket 列表中可以看到已经创建好的 Bucket,点击后可以查看当前 Bucket 的概览:
image.png

2、管理文件

可以通过在线的方式进行文件的管理
image.png

3、阿里云OSS文档

阿里云提供了比较详细的开发文档供使用者参考:
image.png

项目初始化

创建 SpringBoot 项目

image.png
image.png
image.png
image.png

Maven 依赖
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.8.3</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.4</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.9</version>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.8.1</version>
</dependency>
IDEA 安装 lombok 插件(略)

后端服务编写

阿里云OSS配置

在 resource 下新建一个 application-oss.properties

aliyun.endpoint=oss-cn-beijing.aliyuncs.com
aliyun.accessKeyId=LTAI5t9mpendCkALZKtBcqW1
aliyun.accessKeySecret=XXX(你的accessKeySecret)
aliyun.bucketName=malf-bucket
aliyun.urlPrefix=https://malf-bucket.oss-cn-beijing.aliyuncs.com/
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=1000MB

endpoint、bucketName、urlPrefix 在OSS概览页面就可以看到;
accessKeyId、accessKeySecret 需要在 Access Key 里面查看。

配置类代码
package com.malf.config;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * @author 巅峰小词典
 * @description
 * @date 2021/5/20
 * @project springboot_oss
 */
@Configuration
@PropertySource(value = {"classpath:application-oss.properties"})
@ConfigurationProperties(prefix = "aliyun")
@Data
public class AliyunConfig {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private String urlPrefix;

    @Bean
    public OSS oSSClient() {
        return new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }
    
}
后端业务代码
common
package com.malf.common;

import lombok.Data;

/**
 * @author 巅峰小词典
 * @description 用于前后端交互的返回值
 * @date 2021/5/20
 * @project springboot_oss
 */
@Data
public class FileUploadResult {

    // 文件唯一标识
    private String uid;
    // 文件名
    private String name;
    // 状态有:uploading done error removed
    private String status;
    // 服务端响应内容,如:'{"status": "success"}'
    private String response;

}
service
package com.malf.service;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.malf.common.FileUploadResult;
import com.malf.config.AliyunConfig;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.util.List;

/**
 * @author 巅峰小词典
 * @description 使用ossClient操作阿里云OSS,进行上传、下载、删除、查看所有文件等操作,同时可以将图片的url进行入库操作。
 * @date 2021/5/20
 * @project springboot_oss
 */
@Service
public class FileUploadService {

    // 允许上传的格式
    private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", ".jpeg", ".gif", ".png"};

    @Resource
    private OSS ossClient;
    @Resource
    private AliyunConfig aliyunConfig;

    /**
     * 文件上传
     *
     * @param uploadFile
     * @return
     */
    public FileUploadResult upload(MultipartFile uploadFile) {
        // 校验图片格式
        boolean isLegal = false;
        for (String type : IMAGE_TYPE) {
            if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), type)) {
                isLegal = true;
                break;
            }
        }
        // 封装Result对象,并且将文件的byte数组放置到result对象中
        FileUploadResult fileUploadResult = new FileUploadResult();
        if (!isLegal) {
            fileUploadResult.setStatus("error");
            return fileUploadResult;
        }
        // 文件新路径
        String fileName = uploadFile.getOriginalFilename();
        String filePath = getFilePath(fileName);
        // 上传到阿里云
        try {
            ossClient.putObject(aliyunConfig.getBucketName(), filePath, new ByteArrayInputStream(uploadFile.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
            // 上传失败
            fileUploadResult.setStatus("error");
            return fileUploadResult;
        }
        fileUploadResult.setStatus("done");
        fileUploadResult.setResponse("success");
        // 文件路径需要保存到数据库
        fileUploadResult.setName(this.aliyunConfig.getUrlPrefix() + filePath);
        fileUploadResult.setUid(String.valueOf(System.currentTimeMillis()));
        return fileUploadResult;
    }

    /**
     * 生成路径以及文件名
     *
     * @param sourceFileName
     * @return
     */
    private String getFilePath(String sourceFileName) {
        DateTime dateTime = new DateTime();
        return "images/" + dateTime.toString("yyyy") + "/" + dateTime.toString("MM") + "/"
                + dateTime.toString("dd") + "/" + System.currentTimeMillis()
                + RandomUtils.nextInt(100, 9999) + "."
                + StringUtils.substringAfterLast(sourceFileName, ".");
    }

    /**
     * 查看文件列表
     *
     * @return
     */
    public List<OSSObjectSummary> list() {
        // 设置最大个数。
        final int maxKeys = 200;
        // 列举文件。
        ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(aliyunConfig.getBucketName()).withMaxKeys(maxKeys));
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        return sums;
    }

    /**
     * 删除文件
     *
     * @param objectName
     * @return
     */
    public FileUploadResult delete(String objectName) {
        // 根据BucketName,objectName删除文件
        ossClient.deleteObject(aliyunConfig.getBucketName(), objectName);
        FileUploadResult fileUploadResult = new FileUploadResult();
        fileUploadResult.setName(objectName);
        fileUploadResult.setStatus("removed");
        fileUploadResult.setResponse("success");
        return fileUploadResult;
    }

    /**
     * 下载文件
     *
     * @param os
     * @param objectName
     * @throws IOException
     */
    public void exportOssFile(OutputStream os, String objectName) throws IOException {
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(aliyunConfig.getBucketName(), objectName);
        // 读取文件内容。
        BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
        BufferedOutputStream out = new BufferedOutputStream(os);
        byte[] buffer = new byte[1024];
        int lenght = 0;
        while ((lenght = in.read(buffer)) != -1) {
            out.write(buffer, 0, lenght);
        }
        if (out != null) {
            out.flush();
            out.close();
        }
        if (in != null) {
            in.close();
        }
    }

}
controller
package com.malf.controller;

import com.aliyun.oss.model.OSSObjectSummary;
import com.malf.common.FileUploadResult;
import com.malf.service.FileUploadService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @author 巅峰小词典
 * @description
 * @date 2021/5/20
 * @project springboot_oss
 */
@Controller
public class FileUploadController {

    @Resource
    private FileUploadService fileUploadService;

    @RequestMapping("file/upload")
    @ResponseBody
    public FileUploadResult upload(@RequestParam("file") MultipartFile uploadFile) throws Exception {
        return this.fileUploadService.upload(uploadFile);
    }

    @RequestMapping("file/delete")
    @ResponseBody
    public FileUploadResult delete(@RequestParam("fileName") String objectName) throws Exception {
        return this.fileUploadService.delete(objectName);
    }

    @RequestMapping("file/list")
    @ResponseBody
    public List<OSSObjectSummary> list() throws Exception {
        return this.fileUploadService.list();
    }

    @RequestMapping("file/download")
    @ResponseBody
    public void download(@RequestParam("fileName") String objectName, HttpServletResponse response) throws IOException {
        // 浏览器以附件形式下载
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(objectName.getBytes(), "ISO-8859-1"));
        this.fileUploadService.exportOssFile(response.getOutputStream(), objectName);
    }

}
前端页面编写与测试
文件上传页面 upload.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>oss文件上传</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script>
        function uploadfile() {
            $("#fileTypeError").html('');
            // 获得文件名称
            var fileName = $('#file_upload').val();
            // 截取文件类型,如(.jpg)                
            var fileType = fileName.substr(fileName.length - 4, fileName.length);
            // 验证文件类型,此处验证也可使用正则
            if (fileType == '.bmp' || fileType == '.jpg' || fileType == '.jpeg' || fileType == '.gif' || fileType == '.png') {
                $.ajax({
                    url: 'file/upload',// 上传地址
                    type: 'POST',
                    cache: false,
                    data: new FormData($('#uploadForm')[0]),// 表单数据
                    processData: false,
                    contentType: false,
                    success: function (rtn) {
                        if (rtn.status == 'error') {
                            $("#fileTypeError").html('*上传文件类型错误,支持类型: .bmp .jpg .jpeg .gif .png'); // 根据后端返回值,回显错误信息
                        } else {
                            $('div').append('<img src="' + rtn.name + '" style="width: 300px;height: 300px"></img>')
                        }
                    }
                });
            } else {
                $("#fileTypeError").html('*上传文件类型错误,支持类型: .bmp .jpg .jpeg .gif .png');
            }
        }
    </script>
</head>
<body>
<form id="uploadForm" enctype="multipart/form-data">        <!-- 声明文件上传 -->
    <input id="file_upload" type="file" name="file"/>       <!-- 定义change事件,选择文件后触发 -->
    <br/><span style="color: red" id="fileTypeError"></span>    <!-- 文件类型错误回显,此处通过前后端两次验证文件类型 -->
    <br/><input type="button" onclick="uploadfile()" value="上传">
</form>
<div></div>
</body>
</html>

效果展示:
image.png
image.png
image.png

文件管理页面 manager.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>oss文件管理</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script>
        var pre = 'https://malf-bucket.oss-cn-beijing.aliyuncs.com/';
        $(function () {
            listfile();
        });

        // 文件列表
        function listfile() {
            $.ajax({
                url: "http://localhost:8080/file/list",
                type: 'POST',
                success: function (rtn) {
                    console.log(rtn.length);
                    for (var i = 0; i < rtn.length; i++) {
                        $('div').append('<img src="' + pre + rtn[i].key + '" style="width: 300px;height: 300px; padding: 10px" ondblclick="deletefile(this.src)" onclick="downloadfile(this.src)"></img>')
                    }
                }
            });
        }

        // 文件下载
        function downloadfile(src) {
            var fileName = src.split(pre)[1];
            window.location.href = "http://localhost:8080/file/download?fileName=" + fileName;
        }

        // 文件删除
        function deletefile(src) {
            var fileName = src.split(pre)[1];
            var param = {fileName: fileName};
            $.ajax({
                url: "http://localhost:8080/file/delete",
                data: param,
                success: function () {
                    alert('删除成功', fileName);
                    // 删除页面
                    location.reload();
                }
            });
        }
    </script>
</head>
<body>
单击下载oss上的图片、双击删除oss上的图片<br>
<div>

</div>
</body>
</html>

效果展示:
image.png
测试成功,SpringBoot 整合阿里云OSS文件上传、下载、查看、删除的基本框架就搭建成功了。

springboot_oss


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK