SpringBoot案例-文件上传

目录

简介

文件上传前端页面三要素

服务端接收文件

小结

本地储存

实现

代码优化

小结

阿里云OSS

阿里云

阿里云OSS

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

准备工作

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

集成使用

阿里云OSS-使用步骤

阿里云OSS使用步骤

参照SDK编写入门程序

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

引入阿里云OSS工具类

控制类

测试

前后端联调

小结

文件上传介绍

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

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

文件存储方式


简介

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

文件上传前端页面三要素

表单项file

表单提交方式

表单的编码格式

上述页面运行结果为:

服务端接收文件

控制类代码如下:

java 复制代码
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前端页面,设置程序断点,如果不设置断点,程序运行完成之后,接收的临时文件会自动删除。具体示意如下:

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

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

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

小结

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

本地储存

实现

  • 在服务端,接收到上传上来的文件之后,将文件存储在本地服务器磁盘中

  • 具体控制类代码如下
    *

    java 复制代码
    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进行测试

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

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

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

代码优化

  • 存在的问题:当前端传递的文件名称相同时,就会出现文件覆盖的问题

  • 问题的解决:为每一个接收到的文件重新设置一个新的名字即可,新的名字由UUID以及该文件的后缀名组成,UUID使用java自带的aip进行生成,后缀名通过截取文件原名称所得

  • 具体代码如下:
    *

    java 复制代码
    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中,文件上传,默认单个文件允许最大大小为1M,如果需要上传大文件,可以进行如下配置

小结

  • 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

  • 然后进行需要进行的OSS操作

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

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

java 复制代码
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地址

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

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

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

引入阿里云OSS工具类

java 复制代码
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的路径返回
    }

}

控制类

java 复制代码
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);

    }
}

测试

前后端联调

运行成功

小结

文件上传介绍

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

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

文件存储方式

  • 本地存储(无法直接访问、磁盘空间受限、磁盘损坏)
  • 云存储OSS
相关推荐
utmhikari2 分钟前
【架构艺术】Go语言微服务monorepo的代码架构设计
后端·微服务·架构·golang·monorepo
蜡笔小新星4 分钟前
Flask项目框架
开发语言·前端·经验分享·后端·python·学习·flask
计算机学姐8 分钟前
基于Asp.net的驾校管理系统
vue.js·后端·mysql·sqlserver·c#·asp.net·.netcore
欢乐少年19042 小时前
SpringBoot集成Sentry日志收集-3 (Spring Boot集成)
spring boot·后端·sentry
夏天的味道٥3 小时前
使用 Java 执行 SQL 语句和存储过程
java·开发语言·sql
冰糖码奇朵5 小时前
大数据表高效导入导出解决方案,mysql数据库LOAD DATA命令和INTO OUTFILE命令详解
java·数据库·sql·mysql
好教员好5 小时前
【Spring】整合【SpringMVC】
java·spring
浪九天6 小时前
Java直通车系列13【Spring MVC】(Spring MVC常用注解)
java·后端·spring
堕落年代6 小时前
Maven匹配机制和仓库库设置
java·maven
功德+n6 小时前
Maven 使用指南:基础 + 进阶 + 高级用法
java·开发语言·maven