【JavaWeb-文件上传、OSS、文件配置】学习笔记

<<回到导览

文件上传

1.本地储存

1.1.文件上传预览
  • 前端页面文件上传三要素

    1. 表单项 type= “file”

    2. 表单提交方式 post

    3. 表单的enctype属性multipart/form-data

      在这里插入图片描述

  1. 前端代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>上传文件</title>
    </head>
    <body>
        <form action="/upload" method="post" enctype="multipart/form-data">
            姓名: <input type="text" name="username"><br>
            年龄: <input type="text" name="age"><br>
            头像: <input type="file" name="image"><br>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    
  2. 服务端代码

    方法名字要和前端input元素的name相同

    @Slf4j
    @RestController
    public class UploadController {
        @PostMapping("/upload")
        public Result upload(String username, Integer age, MultipartFile image) {
            log.info("文件上传,{},{},{}", username, age, image);
    
            return Result.success();
        }
    }
    
  • 查看文件上传

    1. 打断点调试

      为什么要打断点调试呢?因为我们这里服务器端没有写保存数据的代码,如果不打断点调试,数据传给后端就会被丢弃,我们无法预览到

      在这里插入图片描述

      在这里插入图片描述

    2. 用端口访问html页面(localhost:8080/upload)

      在这里插入图片描述

    3. 点击提交,自动转跳到idea

      在这里插入图片描述

      复制location地址,在文件管理器中浏览,可以看到三个临时文件(就是我们刚刚前端表单中input上传的三个数据)

      在这里插入图片描述

      当请求响应完毕,临时文件就会被删除

1.2.文件本地储存
  • 代码

    @Slf4j
    @RestController
    public class UploadController {
        @PostMapping("/upload")
        public Result upload(String username, Integer age, MultipartFile image) throws IOException {
            log.info("文件上传,{},{},{}", username, age, image);
            // 获取原始文件名
            String originalFilename = image.getOriginalFilename();
    
            // 将文件储存到D:\桌面
            image.transferTo(new File("D:\\桌面\\" + originalFilename));
    
            return Result.success();
        }
    }
    
  • 测试

    在这里插入图片描述

    打开桌面,发现图片保存成功

1.3.本地储存优化

文件名重复优化:

  • 问题:用户上传的文件名可能相同,同一个文件也可能被多次上传,如果这样操作,后面上传文件的文件会覆盖原文件

  • 解决方法:构建唯一的文件名(UUID),这个在阿玮老师的javaee课程中讲到过

    @Slf4j
    @RestController
    public class UploadController {
        @PostMapping("/upload")
        public Result upload(String username, Integer age, MultipartFile image) throws IOException {
            log.info("文件上传,{},{},{}", username, age, image);
            // 获取原始文件名
            String originalFilename = image.getOriginalFilename();
    
            // 构建唯一的文件名
            int index = originalFilename.lastIndexOf(".");// 获取最后.的位置
            String extname = originalFilename.substring(index);// 文件的后缀名
            String newFilename = UUID.randomUUID().toString() + extname;
            log.info("新的文件名,{}", newFilename);
    
            // 将文件储存到D:\桌面
            image.transferTo(new File("D:\\桌面\\" + newFilename));
    
            return Result.success();
        }
    }
    

文件大小限制优化

  • 问题:默认请求下,限制文件最大为1M

    在这里插入图片描述

  • 解决方法:配置请求大小限制

    # 配置单个文件上传大小的限制
    spring.servlet.multipart.max-file-size=10MB
    
    # 配置单个请求最大大小的限制
    spring.servlet.multipart.max-request-size=12MB
    

2.阿里云OSS

阿里云官网:https://www.aliyun.com/

阿里云对象存储0SS (Object Storage Service),是一款海量、安全、低成本、高可靠的云存储服务。使用OSS,您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。

SDK: Software Development Kit 的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK

Bucket:存储空间是用户用于存储对象(Object,就是文件)的容器,所有的对象都必须隶属于某个存储空间。

2.1.开通OSS
  • 创建bucket

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    创建bucket时,不运行打开公共访问,我们可以创建完成后手动打开

    在这里插入图片描述

2.2.获取秘钥

在这里插入图片描述

在这里插入图片描述

注意:自2023年7月5日起,只能在创建时提供秘钥,所以我们要在这里就把秘钥保存好,不然只能重新创建秘钥

在这里插入图片描述

2.3.编写入门程序

oss SDK:https://oss.console.aliyun.com/sdk

  • 在Maven工程中使用OSS Java SDK,只需在pom.xml中加入相应依赖即可。以在中加入3.17.4版本的依赖为例:

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

    如果使用的是Java 9及以上的版本,则需要添加以下JAXB相关依赖。

    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>
    <!-- no more than 2.3.3-->
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.3</version>
    </dependency>
    

    入门程序

    import org.junit.jupiter.api.Test;
    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    public class AliOssTest {
    
        @Test
        public void testOss(){
            // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
            String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
            String accessKeyId = "---------------------";
            String accessKeySecret = "-----------------------";
            // 填写Bucket名称,例如examplebucket。
            String bucketName = "-----------";
            // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
            String objectName = "0001.jpg";
            // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
            // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
            String filePath= "C:\\Users\\Administrator\\Pictures\\Saved Pictures\\10.jpg";
    
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    
            try {
                InputStream inputStream = new FileInputStream(filePath);
                // 创建PutObject请求。
                ossClient.putObject(bucketName, objectName, inputStream);
            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message:" + oe.getErrorMessage());
                System.out.println("Error Code:" + oe.getErrorCode());
                System.out.println("Request ID:" + oe.getRequestId());
                System.out.println("Host ID:" + oe.getHostId());
            } catch (Exception ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message:" + ce.getMessage());
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
    }
    

    官网上的配置有些繁琐,由于这里还没有学配置环境变量,这里就先使用老师这个入门程序样例
    在这里插入图片描述

    配置完毕,运行入门程序,图片上传成功

    在这里插入图片描述

    我们还可以通过url访问这张图片

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <img src="你oss图片的url">
    </body>
    </html>
    
2.4.案例集成

在这里插入图片描述

  • 改造的工具类(com/jia/utils/AliOSSUtils.java)

    /**
     * 阿里云 OSS 工具类
     */
    public class AliOSSUtils {
    
        private String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        private String accessKeyId = "LTAI4GCH1vX6DKqJWxd6nEuW";
        private String accessKeySecret = "yBshYweHOpqDuhCArrVHwIiBKpyqSL";
        private String bucketName = "web-tlias";
    
        /**
         * 实现上传图片到OSS
         */
        public String upload(MultipartFile file) throws IOException {
            // 获取上传的文件的输入流
            InputStream inputStream = file.getInputStream();
    
            // 避免文件覆盖
            String originalFilename = file.getOriginalFilename();
            String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
    
            //上传文件到 OSS
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.putObject(bucketName, fileName, inputStream);
    
            //文件访问路径
            String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
            // 关闭ossClient
            ossClient.shutdown();
            return url;// 把上传到oss的路径返回
        }
    
    }
    
  • 使用工具上传图片并返回图片地址

    @Slf4j
    @RestController
    public class UploadController {
        @Autowired
        private AliOSSUtils ossUtil;
    
        @PostMapping("/upload")
        public Result upload(MultipartFile image) throws IOException {
            log.info("文件上传,文件名:{}", image.getOriginalFilename());
            // 调用阿里云OSS工具类进行文件上传
            String url = ossUtil.upload(image);
            log.info("文件上传完成,文件访问参数的url:{}", url);
            return Result.success(url);
        }
    }
    

    在这里插入图片描述

    在这里插入图片描述

3.配置文件

3.1.参数配置化

在OSS章节,我们将OSS的参数配置到了utils/AliOSSUtils.java文件,我们可以集中配置这些文件,方便维护和管理

  • utils/AliOSSUtils.java

    @Value注解通常用于外部配置的属性注入

    @Component
    public class AliOSSUtils {
        @Value("${aliyun.oss.endpoint}")
        private String endpoint ;
    
        @Value("${aliyun.oss.accessKeyId}")
        private String accessKeyId ;
    
        @Value("${aliyun.oss.accessKeySecret}")
        private String accessKeySecret ;
    
        @Value("${aliyun.oss.bucketName}")
        private String bucketName ;
        // ...
    }
    
  • application.properties

    aliyun.oss.endpoint=https://oss-cn-chengdu.aliyuncs.com
    aliyun.oss.accessKeyId=LTAI5tFmqYKEvooT4xUTFsew
    aliyun.oss.accessKeySecret=P2nDkC30PnVIiqUTUCQrygyhczc6Bk
    aliyun.oss.bucketName=jiaqi123
    
3.2.yml配置文件

相比于properties配置文件,yml/yaml配置文件具有层次结构分明的特点(yaml配置文件和properties配置文件存放于同一目录下)。

  • 基本语法

    1. 大小写敏感
    2. 数值前边必须有空格,作为分隔符
    3. 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格)
    4. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
    5. #表示注释,从这个字符一直到行尾,都会被解析器忽略
  • 示例

    1. 对象、Map集合

      user:
      	name: Tom
      	age: 20
      	address: chengdu
      
    2. 数组、List集合、Set集合

      hobby:
      	-Tom
      	-Jack
      	-Bob
      
  • 修改案例配置文件

    1. 修改前

      spring.application.name=emp
      
      # 数据库配置
      spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
      spring.datasource.username=root
      spring.datasource.password=123456
      
      # mybatis日志输出到控制台
      mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
      
      # 驼峰命名自动映射开关
      mybatis.configuration.map-underscore-to-camel-case=true
      
      # 配置文件上传大小
      spring.servlet.multipart.max-file-size=10MB
      spring.servlet.multipart.max-request-size=12MB
      
      # 阿里云OSS
      aliyun.oss.endpoint=https://oss-cn-chengdu.aliyuncs.com
      aliyun.oss.accessKeyId=LTAI5tFmqYKEvooT4xUTFsew
      aliyun.oss.accessKeySecret=P2nDkC30PnVIiqUTUCQrygyhczc6Bk
      aliyun.oss.bucketName=jiaqi123
      
    2. 修改后

      spring:
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: mysql://localhost:3306/mybatis
          username: root
          password: 123456
        servlet:
          multipart:
            max-file-size: 10MB
            max-request-size: 12MB
      mybatis:
        configuration:
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
          map-underscore-to-camel-case: true
      
      aliyun:
        oss:
          endpoint: https://oss-cn-chengdu:aliyuncs:com
          accessKeyId: LTAI5tFmqYKEvooT4xUTFsew
          accessKeySecret: P2nDkC30PnVIiqUTUCQrygyhczc6Bk
          bucketName: jiaqi123
      
3.3.@ConfigurationProperties

每个使用配置项的地方都要用@Value指定配置值,极为不便,我们可以用@ConfigurationProperties简化@Value指定配置值

  • 简化前

    @Component
    public class AliOSSUtils {
        @Value("${aliyun.oss.endpoint}")
        private String endpoint ;
    
        @Value("${aliyun.oss.accessKeyId}")
        private String accessKeyId ;
    
        @Value("${aliyun.oss.accessKeySecret}")
        private String accessKeySecret ;
    
        @Value("${aliyun.oss.bucketName}")
        private String bucketName ;
        // ...
    }
    
  • 简化后

    配置时,属性名要相同

    @Data
    @Component
    @ConfigurationProperties(prefix = "aliyun.oss")
    public class AliOSSUtils {
        private String endpoint ;
        private String accessKeyId ;
        private String accessKeySecret ;
        private String bucketName ;
        // ...
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值