SpringBoot案例-文件上传

目录

简介

文件上传前端页面三要素

 服务端接收文件

小结

本地储存

实现

代码优化

小结 

阿里云OSS

阿里云

阿里云OSS

使用第三方服务--通用思路

 准备工作

参照官方SDK代码,编写入门程序

集成使用

阿里云OSS-使用步骤

阿里云OSS使用步骤

参照SDK编写入门程序

案例集成OSS (文件上传接口的实现)

 引入阿里云OSS工具类

控制类

测试 

前后端联调 

小结

文件上传介绍

前端页面三要素(file表单项、post方法、multipart/form-data)

服务端接口接收文件(Multipart)

文件存储方式


简介

  • 文件上传,是指将本地图片、视频、音频等文件上传至服务器,供其他用户浏览或者下载的过程
  • 文件上传在项目中应用非常广泛,我们经常发微博、发朋友圈都要用到文件上传功能。

文件上传前端页面三要素

表单项file

表单提交方式

表单的编码格式

SpringBoot案例-文件上传_第1张图片

上述页面运行结果为:

SpringBoot案例-文件上传_第2张图片

 服务端接收文件

控制类代码如下:

package com.example.tlias.controller;

import com.example.tlias.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@Slf4j

public class UpLoadController {
    @PostMapping("upload")
    public Result upload(String username, Integer age, MultipartFile image) {
        log.info("文件上传,name:{},age:{},image:{}", username, age, image);
        return Result.success();
    }

}

 调试运行SpringBoot项目,在浏览器中访问html前端页面,设置程序断点,如果不设置断点,程序运行完成之后,接收的临时文件会自动删除。具体示意如下:

SpringBoot案例-文件上传_第3张图片

然后在浏览器中访问前端页面

SpringBoot案例-文件上传_第4张图片

点击提交后, 程序终端显示如下:

SpringBoot案例-文件上传_第5张图片

 显示接收到前端的数据以及数据临时存放的位置

小结

  • 前端页面三要素
    • 表单项 type=“file”
    • 表单提交方式 post
    • 表单的enctype属性 multipart/form-data
  • 服务端接收wenjian
    • MultipartFile

本地储存

实现

  • 在服务端,接收到上传上来的文件之后,将文件存储在本地服务器磁盘中
  • 具体控制类代码如下
    • package com.example.tlias.controller;
      
      import com.example.tlias.pojo.Result;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.multipart.MultipartFile;
      
      import java.io.File;
      import java.io.IOException;
      
      @RestController
      @Slf4j
      
      public class UpLoadController {
          @PostMapping("upload")
          public Result upload(String username, Integer age, MultipartFile image) throws IOException {
              log.info("文件上传,name:{},age:{},image:{}", username, age, image);
              //  todo 获取原始文件名
              String name = image.getOriginalFilename();
              //  todo 将文件存储在服务器指定的磁盘目录中
              image.transferTo(new File("D:\\downloadFile\\" + name));
              return Result.success();
          }
      
      }
      

使用psotman进行测试

具体请求路径以及请求参数如下

SpringBoot案例-文件上传_第6张图片

在对应的文件目录中显示如下:

SpringBoot案例-文件上传_第7张图片

成功将前端传递的文件存储到本地服务器的磁盘中 

代码优化

  • 存在的问题:当前端传递的文件名称相同时,就会出现文件覆盖的问题
  • 问题的解决:为每一个接收到的文件重新设置一个新的名字即可,新的名字由UUID以及该文件的后缀名组成,UUID使用java自带的aip进行生成,后缀名通过截取文件原名称所得
  • 具体代码如下:
    • package com.example.tlias.controller;
      
      import com.example.tlias.pojo.Result;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.multipart.MultipartFile;
      
      import java.io.File;
      import java.io.IOException;
      import java.util.UUID;
      
      @RestController
      @Slf4j
      
      public class UpLoadController {
          @PostMapping("upload")
          public Result upload(String username, Integer age, MultipartFile image) throws IOException {
              log.info("文件上传,name:{},age:{},image:{}", username, age, image);
              //  todo 获取原始文件名,但是不同文件的原始文件名可能相同
              String name = image.getOriginalFilename();
              // todo 构造唯一文件名--uuid(通用唯一识别码)
              // 获取文件后缀名
              int index = name.lastIndexOf(".");//获取最后的.的索引位置
              String extname = name.substring(index);//进行截取
              String newName = UUID.randomUUID().toString() + extname;//创建唯一文件名
              log.info("获取到的新的文件名为:{}", newName);
              //  todo 将文件存储在服务器指定的磁盘目录中
              image.transferTo(new File("D:\\downloadFile\\" + newName));
              return Result.success();
          }
      
      }
      

使用postman重新发送相同的请求,运行结果如下:

 SpringBoot案例-文件上传_第8张图片

问题成功解决 

在SpringBoot中,文件上传,默认单个文件允许最大大小为1M,如果需要上传大文件,可以进行如下配置

SpringBoot案例-文件上传_第9张图片

小结 

  • String getOriginalFilename() -->获取原始文件名
  • void transferTo(File dest)-->将接受文件转存到磁盘文件中
  • long getSize() -->获取文件大小,单位字节(byte) 1KB=1024字节
  • byte[ ] getBytes() --> 获取文件内容的字节数组
  • InputStream getInputStream() -->获取接收到的文件内容的输入流

阿里云OSS

阿里云

  • 阿里云是阿里巴巴集团旗下全球领先的云计算公司,也是国内最大的云服务提供商

阿里云OSS

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

使用第三方服务--通用思路

 准备工作

参照官方SDK代码,编写入门程序

  • SDK是软件开发工具包(Software Development Kit)的缩写,它是一组用于开发特定软件应用或平台的工具、库和文档的集合。SDK提供了开发者所需的工具和资源,以便他们能够更轻松地创建、测试和部署软件应用。SDK通常包含编译器、调试器、API文档、示例代码和其他开发工具,以及与特定平台或操作系统交互的库和组件。开发者可以使用SDK来构建应用程序、插件、扩展或其他软件组件,以便与特定的软件、硬件或服务进行集成。

集成使用

阿里云OSS-使用步骤

阿里云OSS使用步骤

注册阿里云---充值(选做)---开通对象存储服务(OSS)---创建bucket---获取AccessKey(密钥)---参照官方SDK编写入门使用----案例集成OSS

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

具体使用步骤参照一下文件:

【腾讯文档】SpringBoot案例所需文档
https://docs.qq.com/doc/DUkRiTWVaUmFVck9N

参照SDK编写入门程序

根据阿里云官方提供的文档进行操作即可

  • 首先安装Java JDK
    • SpringBoot案例-文件上传_第10张图片
  • 然后进行需要进行的OSS操作 
    • SpringBoot案例-文件上传_第11张图片

     复制对应的代码即可,根据自己的信息修改其中的具体代码

我要使用文件上传的功能,具体代码如下:

package com.example.tlias;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;

import java.io.FileInputStream;
import java.io.InputStream;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        // todo 指定OSS服务地址

        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // todo 设置访问凭证

        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        // todo 指定文件所存储的bucket名字(bucketName),以及文件的名称(objectName)

        String bucketName = "examplebucket";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "exampledir/exampleobject.txt";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        // todo 指定本地要上传的文件

        String filePath = "D:\\localpath\\examplefile.txt";

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

        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
        } 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 (ClientException 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();
            }
        }
    }
} 

修改完具体的参数之后,允许一下该java程序,允许结果如下:

运行成功 

 并且会为每一个文件设置一个访问的url地址

SpringBoot案例-文件上传_第12张图片

案例集成OSS (文件上传接口的实现)

 在员工案例中的对于新增员工接口功能的实现中,还没有实现对于员工头像信息的上传,头像上传功能的实现,参照接口文档中的文件上传接口,接口文档的具体链接如下:

https://hkm-web.oss-cn-beijing.aliyuncs.com/%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3

 引入阿里云OSS工具类

package com.example.tlias.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.UUID;

/**
 * 阿里云 OSS 工具类
 */
@Component
public class AliOSSUtils {

    // todo 指定OSS服务地址
    private String endpoint = "你自己的";
    // todo 设置密钥账号和密码
    private String accessKeyId = "你自己的";
    private String accessKeySecret = "你自己的";
    // todo 设置文件存储buket
    private String bucketName = "你自己的";

    /**
     * 实现上传图片到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的路径返回
    }

}

控制类

package com.example.tlias.controller;

import com.example.tlias.pojo.Result;
import com.example.tlias.utils.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@RestController
@Slf4j

public class UpLoadController {
    // todo 文件存储到本地
//    @PostMapping("/upload")
//    public Result upload(String username, Integer age, MultipartFile image) throws IOException {
//        log.info("文件上传,name:{},age:{},image:{}", username, age, image);
//        //  todo 获取原始文件名,但是不同文件的原始文件名可能相同
//        String name = image.getOriginalFilename();
//        // todo 构造唯一文件名--uuid(通用唯一识别码)
//        // 获取文件后缀名
//        int index = name.lastIndexOf(".");//获取最后的.的索引位置
//        String extname = name.substring(index);//进行截取
//        String newName = UUID.randomUUID().toString() + extname;//创建唯一文件名
//        log.info("获取到的新的文件名为:{}", newName);
//        //  todo 将文件存储在服务器指定的磁盘目录中
//        image.transferTo(new File("D:\\downloadFile\\" + newName));
//        return Result.success();
//    }
// todo 文件存储至阿里云OSS
    @Autowired
    private AliOSSUtils aliOSSUtils;

    @PostMapping("/upload")
    public Result upload(MultipartFile image) throws IOException {
        log.info("文件上传至阿里云,文件名:{}", image.getOriginalFilename());
        // 调用阿里云OSS工具进行文件上传
        String url = aliOSSUtils.upload(image);
        log.info("文件上传完成,文件url地址为:{}", url);
        return Result.success(url);

    }
}

测试 

SpringBoot案例-文件上传_第13张图片

前后端联调 

SpringBoot案例-文件上传_第14张图片

SpringBoot案例-文件上传_第15张图片 SpringBoot案例-文件上传_第16张图片

SpringBoot案例-文件上传_第17张图片

运行成功  

小结

文件上传介绍

前端页面三要素(file表单项、post方法、multipart/form-data)

服务端接口接收文件(Multipart)

文件存储方式

  • 本地存储(无法直接访问、磁盘空间受限、磁盘损坏)
  • 云存储OSS

你可能感兴趣的:(Java,Web学习跟踪笔记,spring,boot,后端,java,阿里云,OSS,云服务)