文件上传

213 阅读4分钟

一、文件上传

1. 文件上传功能

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

1.1 客户端上传文件三要素

客户端要把文件上传到服务端,需要满足一下三要素,否则仅仅是提交文件名,而不会提交文件内容:

  • 使用表单方式提交,且表单提交方式是POST
  • 表单的enctype属性要设置为multipart/form-data
  • 表单里要有文件选择框,且文件选择框必须有name属性<input type="file" name="表单参数名">

示例:demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传-示例</title>
</head>
<body>
    <!-- 
		1. 使用表单方式提交数据,且表单提交方式为post 
		2. 表单form标签的enctype属性要设置为multipart/form-data
	 -->
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        <!-- 3. 表单里要有文件选择框,且必须有name属性 -->
        <input type="file" name="avatar"><br>
        <button>提交</button>
    </form>
</body>
</html>

1.2 服务端接收文件

在Controller里接收文件数据:

  • 需要使用MultipartFile类型的参数,MultipartFile对象的常用方法:

    • getOriginalFilename():获取原始文件名(客户端上传的文件名称)
    • getSize():获取文件的大小,单位是byte字节
    • getInputStream():获取字节输入流对象,用于获取文件数据
    • transferTo(File dest):把文件数据存储到本地磁盘上
  • 默认允许上传的文件大小为1M,可以通过修改配置文件来调整限制

修改允许上传的文件大小

修改配置文件application.properties

#设置:一次请求最大允许提交20MB。默认10MB
spring.servlet.multipart.max-request-size=20MB
#设置:一个文件最大允许10MB。默认1MB
spring.servlet.multipart.max-file-size=10MB

2. 本地存储文件

所谓本地存储文件,是客户端把文件上传到服务器之后,服务器把文件直接存储到自己的磁盘里。

好处:简单

缺点:

  • 本地磁盘空间有限,不能存储太多文件;且不方便扩容
  • 本地存储文件,没有备份,一旦磁盘出现问题,就会丢失文件
  • 维护管理不方便

示例代码:

@Slf4j
@RestController
@RequestMapping("/file")
public class FileController {
​
    @PostMapping("/upload")
    public Result upload(String name, MultipartFile avatar) throws IOException {
        log.info("name={}", name);
        //重命名文件
        //  1. 获取原始文件名。比如:100.jpg
        String filename = avatar.getOriginalFilename();
        //  2. 截取得到后缀名。比如:.jpg
        String suffix = filename.substring(filename.lastIndexOf("."));
        //  3. 重新生成新的文件名。比如:2ceea81e-2a4d-4709-8332-367ea4e34e23.jpg
        filename = UUID.randomUUID().toString() + suffix;
        //保存文件到本地磁盘
        avatar.transferTo(Paths.get("E:\" + filename));
        log.info("文件已保存到:E:/{}", filename);
        return Result.success();
    }
}

3. 阿里云OSS存储

3.1 介绍

阿里云对象存储 OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供最高可达 99.995 % 的服务可用性。多种存储类型供选择,全面优化存储成本。

3.2 阿里云OSS使用示例

阿里云OSS文档:help.aliyun.com/zh/oss/deve…

阿里云SDK介绍:help.aliyun.com/zh/oss/deve…

上传文件示例代码:help.aliyun.com/zh/oss/deve…

添加依赖

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

上传示例

public class AliyunOSSTest {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider("你的accessKeyId", "你的accessKeySecret");
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "你的bucket名称";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "aa/mm.jpg";
        // 填写本地文件的完整路径,例如D:\localpath\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath= "C:\Users\sdf\Desktop\img\32.jpg";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialProvider);
        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            System.out.println(result);
        } 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();
            }
        }
    }
} 

4. 上传员工头像

分析

02.新增员工时上传头像.png

实现

阿里云OSS工具类

@Component
public class AliOSSUtils {

    private String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    private String accessKeyId = "*************";
    private String accessKeySecret = "**************";
    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的路径返回
    }

}

  1. 在类上添加@Component
  2. 修改配置参数endpoind、accessKeyId、accessKeySecret、bucket名称等,改成自己的

如果要上传文件时:

  • 只要使用@Autowired注入AliOSSUtils对象,调用它的upload方法就可以了

UploadController

@Slf4j
@RestController
public class UploadController {
    @Autowired
    private AliOSSUtils ossUtils;
    @PostMapping("/upload")
    public Result upload(MultipartFile image) throws IOException {
        String url = ossUtils.upload(image);
        return Result.success(url);
    }
}