P146 案例-文件上传-简介

文件上传,将本地图片、视频等文件上传到服务器,供其他用户浏览下载的过程。

文件上传前端页面三要素:

在这里插入图片描述

如果前端表单的编码格式选择的默认编码方式x-www.form-urlencoded,则提交的文件仅仅是文件名,文件内容没有提交到服务端,所以表单编码方式应该选择multipart/form-data,不然不能提交真正的文件内容。

图片、音频上传后文件内容可能是乱码。

服务端如何接收上传文件呢?

例如:springboot当中提供了multipartfile这个api,利用这个api可以接收上传文件,注意保证参数名和前端属性名一致。

在这里插入图片描述

P147、148、149、150 案例-文件上传-本地存储-OSS存储

服务端接收后是临时文件,之后就清除了。

两种存储方案:

1、本地存储

将文件存储在本地服务器磁盘中,multipartfile提供了保存磁盘的方法transferto。

下面是使用案例:

 @PostMapping("/upload")
    public Result upload(String name, Integer age, MultipartFile image) throws Exception{
        log.info("文件上传:{}, {}, {}",name, age, image);
        // 获取原始文件名
        String originalFilename = image.getOriginalFilename();
        image.transferTo(new File("E:\\mycodes\\ideaProject\\javaweb\\javaweb_project\\springboot-tlias\\springboot-tlias\\src\\main\\resources\\img\\"+originalFilename));
        return Result.success();
    }

对上述操作优化:如果直接采用原始名存储,则会造成存在相同名称的文件会相互冲突,后来的文件会覆盖掉前面的文件,因此需要保证每一个文件是唯一的,如何构造唯一的文件名?

时间戳也不一定,采用uuid解决。

uuid:通用唯一识别码,长度固定的字符串且不重复,

//    uuid示例
//    java.util中有UUID工具类
    @Test
    public void testUuid(){
    for (int i = 0; i < 100; i++){
        String s = UUID.randomUUID().toString();
        System.out.println(s);

    }
    }

输出如下所示:输出32位,4个-,总长36位,

在这里插入图片描述

但是uuid不存在文件名后缀,所以需要添加文件扩展名,如何获取文件扩展名?截取.之后的

因此使用UUID改进后的方法如下所示:

 @PostMapping("/upload")
    public Result upload(String name, Integer age, MultipartFile image) throws Exception{
        log.info("文件上传:{}, {}, {}",name, age, image);
        // 获取原始文件名
        String originalFilename = image.getOriginalFilename();
        // 获取文件扩展名,即.之后的
        int index = originalFilename.lastIndexOf(".");
        // 从index截取到尾部获得扩展名
        String extname = originalFilename.substring(index);
        String newFileName = UUID.randomUUID().toString() + extname;
        log.info("获取到新的文件名:{}", newFileName);
        image.transferTo(new File("E:\\mycodes\\ideaProject\\javaweb\\javaweb_project\\springboot-tlias\\springboot-tlias\\src\\main\\resources\\img\\"+newFileName));
        return Result.success();
    }

能够成功以UUID保存文件

默认情况下上传文件不能超过超过1M,否则会报错,如果需要上传大文件,可以进行如下配置:在Properties中

# 配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB

# 配置单个请求最大上传大小,一次请求可上传多个 文件
spring.servlet.multipart.max-request-size=100MB

存储本地磁盘缺点:

  • 无法直接访问本地

  • 服务器磁盘满了不方便扩容

  • 如果磁盘坏了则会造成损失

multipartfile常用方法:

  • String getOriginalFilename()获取原始文件名

  • void transferTo(File dest)将接收的文件转存到磁盘文件中

  • long getSize()获取文件的大小,单位为字节

  • byte[] getBytes()获取文件内容的字节数组

  • InputStream getInputStream()获取接收到的文件内容的输入流

不用本地存储,常用

  • 项目组自己搭建的文件存储服务,例如分布式服务或集群

  • 使用云服务,方便可靠

2、云存储

阿里云,“云”即互联网,云服务即通过互联网提供各种各样的服务。

OSS对象存储服务,object storage service,可通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。

您可以进行以下操作:

  • 创建一个或者多个存储空间,向每个存储空间中添加一个或多个文件。

  • 通过获取已上传文件的地址进行文件的分享和下载。

  • 通过修改存储空间或文件的属性或元信息来设置相应的访问权限。

  • 在阿里云管理控制台执行基本和高级OSS任务。

  • 使用阿里云开发工具包或直接在应用程序中进行RESTful API调用执行基本和高级OSS任务

学习如何使用云服务。

第三方服务通用思路:

  • 准备工作

  • 参照官方SDK编写入门程序

  • 集成使用

bucket是阿里云OSS中的存储空间,即用户存储对象的容器,所有的对象都必须隶属于某个存储空间。使用步骤

在这里插入图片描述

可在官方使用文档中进行查看手册,创建好bucket之后,在项目中引入依赖

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

编写测试单元进行测试,参照文件流上传示例,下面是核心操作

 // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (OSSException oe) {

完整如下:可以上传成功,并且上传的每个文件还有可访问的url。

@Test
    public void testOss(){
        String endpoint = "oss-cn-beijing.aliyuncs.com"; // 查询阿里云bucket
        String accessKeyId = "";
        String accessKeySecret = "";
        String bucketName = "hemastudy";
        String objectName = "0001.jpg";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath= "E:\\download\\3bi4.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();
            }
        }

    }

将OSS集成到案例中,将员工图像上传到OSS中。

  • 接收上传的图片

  • 将图片存储起来吗

  • 返回图片访问的url

使用标签展示图片。

实现阿里云上传的工具类,调用上传方法返回url。可将该类加到IOC容器管理,添加注解@Component。注意自己修改endpoint要加上https://

/**
 * 阿里云 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的路径返回
    }

}

使用方法:

    @PostMapping("/upload1")
    public Result upload(MultipartFile image) throws IOException {
        String url = aliOSSUtils.upload(image);
        return Result.success();
    }

小结:

  • 了解文件上传,文件上传前端页面三要素

  • 服务端接收文件Multipartfile

  • 文件存储

P151、P152 案例-修改员工-查询回显

修改员工两步:先要依据点击的记录请求服务端返回数据用于页面回显展示,保存需要更新数据。

查询回显:按照id进行查询即可。

修改员工采用动态SQL,使用判断是否需要更新。

P153 案例-配置文件-参数配置化

springboot的配置文件。

问题分析,怎样将一些参数的设置进行集中管理?

配置文件一般只有一个,可以考虑将参数定义在配置文件中,kye=value的形式。

如果在类中需要使用这些参数的话,如何读取到?方式是通过IO流来读取配置文件,解析配置文件中的值,然后为类中成员赋值。

上述方法在springboot中已经解决了,提供了一个注解@value,用于外部配置的属性注入,具体用法@value("${配置文件中的key}")

多行编辑,alt+鼠标左键,

例如:

   @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;

P154 案例-配置文件-yml配置文件

springboot中提供了多种属性配置方式:

  • application.properties:key = value的形式

  • application.yml

  • application.yaml ,两者配置形式相同,配置形式为key:value

例如设置内嵌的tomcat端口号修改为9000

server:
  port: 9000
  address:

下面是常见的配置文件格式对比:推荐使用yml格式的配置文件

在这里插入图片描述

yml格式的基本语法

  • 大小写敏感

  • 数值前边必须有空格,作为分隔符

  • 使用缩进表示层级关系,缩进时不允许使用Tab键,只能用空格

  • 缩进的空格数不重要,相同层级的元素左侧对齐

  • #表示注释,

yml中常见的数据格式:

  • 对象/Map集合,例如

user:
name: xxx
age: 12
password: xxx



- 数组/List/Set集合

  ```YAML
hobby:
  - java
  - C
  - game
  - sport

使用yml配置文件同样可以运行。

P155 案例-配置文件-@Configuration

如果采用value注解注入配置文件中的参数,当比较多的时候则会比较繁琐、臃肿。

springboot中有解决,可以自动将配置文件中的值自动注入到需要的类成员中,注意key需要对应,并且为实体类属性提供get、set方法,并将实体类交给IOC容器管理,如果有前缀则要添加,则前面的aliossutils可以修改为如下形式:

@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOssproperties {
    private String endpoint;
    private String accessKeyId;
    private String ccessKeySecret;
    private String ucketName;
}


// 在使用的 时候直接注入bean对象即可

需要引入依赖:自动识别被configurationproperties标识的对象

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
  </dependency>

@ConfigurationProperties与@Value的区别:

在这里插入图片描述

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐