SpringBoot文件上传(OSS)


文档: https://help.aliyun.com/document_detail/32007.html

1. 概念

  • 「OSS」的英文全称是Object Storage Service,翻译成中文就是「对象存储服务」,官方一点解释就是对象存储是一种使用HTTP API存储和检索非结构化数据和元数据对象的工具

  • 白话文解释就是将系统所要用的文件上传到云硬盘上,该云硬盘提供了文件下载、上传等一列服务,这样的服务以及技术可以统称为OSS,业内提供OSS服务的厂商很多,知名常用且成规模的蓝队云等在这里插入图片描述

  • OSS相关的术语

    • 存储空间(Bucket): 存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间
    • 对象/文件(Object): 对象是 OSS 存储数据的基本单元,也被称为OSS的文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的Key来标识
    • 地域(Region): 地域表示 OSS 的数据中心所在物理位置。您可以根据费用、请求来源等综合选择数据存储的地域。详情请查看OSS已经开通的Region
    • 访问域名(Endpoint): Endpoint 表示OSS对外服务的访问域名。OSS以HTTP RESTful API的形式对外提供服务,当访问不同地域的时候,需要不同的域名。通过内网和外网访问同一个地域所需要的域名也是不同的。具体的内容请参见各个Region对应的Endpoint,例如杭州 Region 的外网 Endpoint 是 oss-cn-hangzhou.aliyuncs.com,内网 Endpoint 是 oss-cn-hangzhou-internal.aliyuncs.com
    • 访问密钥(AccessKey): AccessKey,简称 AK,指的是访问身份验证中用到的AccessKeyId 和AccessKeySecret。OSS通过使用AccessKeyId 和AccessKeySecret对称加密的方法来验证某个请求的发送者身份。AccessKeyId用于标识用户,AccessKeySecret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,其中AccessKeySecret 必须保密,对于OSS来说,AccessKey的来源有:
      • Bucket 的拥有者申请的 AccessKey
      • 被 Bucket 的拥有者通过 STS 授权给第三方请求者的 AccessKey
      • 被Bucket 的拥有者通过 RAM 授权给第三方请求者的 AccessKey

2. 数据准备

免费的话可以用七牛云,这里我是申请了阿里云的OSS,这里主要是讲一下我们项目需要用的一些oss信息,等下yml配置需要用到

  • access-key-id和access-key-secretimage-20220506221326326

  • bucket和endpointimage-20220506221524805

  • 上传的文件夹image-20220506221621167

3. 实战

  • 依赖

     <!-- mvc的自动配置 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    
    <!-- oss-->
    <dependency>
        <groupId>com.aliyun.oss</groupId>
        <artifactId>aliyun-sdk-oss</artifactId>
        <version>3.10.2</version>
    </dependency>
    
  • yml文件配置

    # oss
    oss:
      access-key-id: xxx
      access-key-secret: xxx 
      bucket: typora-aliyun
      endpoint: oss-cn-shanghai.aliyuncs.com
      dir: file/
    
    @Component
    @ConfigurationProperties(prefix = "oss")
    public class OSSProperties{
    
        private String endpoint;
    
        private String accessKeyId;
    
        private String accessKeySecret;
    
        private String bucket;
    
        private String dir;
    	
    	//省略getset
    }
    
  • 配置类

    @Configuration
    public class OSSConfig {
    
        @Autowired
        private OSSProperties ossProperties;
    
        @Bean
        public OSSClient ossClient(){
            OSS ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                    ossProperties.getAccessKeyId(),
                    ossProperties.getAccessKeySecret());
            return (OSSClient) ossClient;
        }
    }
    
  • 工具类

    @Component
    public class OSSUtil {
    
        @Autowired
        private OSSProperties ossProperties;
    
        @Autowired
        private OSSClient ossClient;
    
        /**
         * 上传图片
         *
         * @param file
         * @param fileName
         * @return
         * @throws IOException
         */
        public String uploadImg2Oss(MultipartFile file, String fileName) throws IOException {
            try {
                InputStream inputStream = file.getInputStream();
                this.uploadFile2OSS(inputStream, fileName);
                String url = "https://" + ossProperties.getBucket() + "." + ossProperties.getEndpoint() + "/" + ossProperties.getDir() + fileName;
                return url;
            } catch (Exception e) {
                throw new IOException("图片上传失败");
            }
        }
    
        /**
         * 上传到OSS服务器 如果同名文件会覆盖服务器上的
         *
         * @param instream 文件流
         * @param fileName 文件名称 包括后缀名
         * @return 出错返回"" ,唯一MD5数字签名
         */
        public String uploadFile2OSS(InputStream instream, String fileName) {
            String ret = "";
            try {
                // 创建上传Object的Metadata
                ObjectMetadata objectMetadata = new ObjectMetadata();
                objectMetadata.setContentLength(instream.available());
                objectMetadata.setCacheControl("no-cache");
                objectMetadata.setHeader("Pragma", "no-cache");
                objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
                objectMetadata.setContentDisposition("inline;filename=" + fileName);
                // 上传文件
                PutObjectResult putResult = ossClient.putObject(ossProperties.getBucket(), ossProperties.getDir() + fileName, instream, objectMetadata);
                ret = putResult.getETag();
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } finally {
                try {
                    if (instream != null) {
                        instream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return ret;
        }
    
        /**
         * Description: 判断OSS服务文件上传时文件的contentType
         */
        public static String getcontentType(String filenameExtension) {
            if (filenameExtension.equalsIgnoreCase("bmp")) {
                return "image/bmp";
            }
            if (filenameExtension.equalsIgnoreCase("gif")) {
                return "image/gif";
            }
            if (filenameExtension.equalsIgnoreCase("jpeg") || filenameExtension.equalsIgnoreCase("jpg")
                    || filenameExtension.equalsIgnoreCase("png")) {
                return "image/jpeg";
            }
            if (filenameExtension.equalsIgnoreCase("html")) {
                return "text/html";
            }
            if (filenameExtension.equalsIgnoreCase("txt")) {
                return "text/plain";
            }
            if (filenameExtension.equalsIgnoreCase("vsd")) {
                return "application/vnd.visio";
            }
            if (filenameExtension.equalsIgnoreCase("pptx") || filenameExtension.equalsIgnoreCase("ppt")) {
                return "application/vnd.ms-powerpoint";
            }
            if (filenameExtension.equalsIgnoreCase("docx") || filenameExtension.equalsIgnoreCase("doc")) {
                return "application/msword";
            }
            if (filenameExtension.equalsIgnoreCase("xml")) {
                return "text/xml";
            }
            return "image/jpeg";
        }
    
    }
    
  • controller

    @Controller
    @RequestMapping("/sysFile")
    public class SysFileController {
    
        @Autowired
        private ISysFileService fileService;
    
        @Autowired
        private OSSUtil ossUtil;
    
        @GetMapping("/toFilePage")
        public String toFilePage(){
            return "file";
        }
    
        @PostMapping("/uploadOss")
        @ResponseBody
        public AjaxResult uploadOss(@RequestParam(value = "file", required = true) MultipartFile file) throws Exception {
            // 原始文件名称,如test.jpg
            String fileName = file.getOriginalFilename();
            // 唯一的文件名称
            String newFileName = getTime()+ "_" + fileName;
            // 上传文件,并获取oss上图片的地址,例如:https://typora-aliyun.oss-cn-shanghai.aliyuncs.com/file/20220506202723_test.jpg
            String url = ossUtil.uploadImg2Oss(file, newFileName);
            //存进数据库
            if (url != null) {
                SysFile sysFile = new SysFile();
                sysFile.setFileName(fileName);
                sysFile.setFileUrl(url);
                fileService.save(sysFile);
            }
            return AjaxResult.suc();
    
        }
    
        public String getTime(){
            String curTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            return curTime;
        }
    }
    
  • 页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>文件上传</title>
    </head>
    <body>
    
    <form enctype="multipart/form-data" method="POST" action="/sysFile/uploadOss">
        <input type="file" name="file" />
        <input type="submit" value="upload" />
    </form>
    
    </body>
    </html>
    

    准备完成之后,访问http://localhost:8080/sysFile/toFilePage,上传我们的图片, 可以在阿里oss看到我们上传的图片

    image-20220506221702598

4. 总结

上面实战的只是最简单的上传功能,适合小文件上传,oss其实还支持更加复杂的文件操作,比如断点,追加,分片等,需要自己去看一下文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值