springboot中Controller内文件上传到本地以及阿里云

上传文件的基本操作

html 复制代码
<form action="/upload" method="post" enctype="multipart/form-data">  
    <h1>登录</h1>  
    姓名:<input type="text" name="username" required><br>  
    年龄:<input type="text" name="age" required><br>  
    头像:<input type="file" name="file" required><br>  
    <input type="submit" value="提交">  
</form>  
java 复制代码
// Java接收前端发来的文件

@RestController
public class UploadController {
    private static final ch.qos.logback.classic.Logger log = (Logger) LoggerFactory.getLogger(UploadController.class);
    @PostMapping(path = "/upload")
    public Result upload(String username, Integer age, MultipartFile file){
        log.info("接收参数:" + username + age + file);
        return Result.success();
    }
}

注意:springboot项目启动后,打开这个index.html的页面要输入:localhost:8080/index.html

接下来通过断点调试获取查看前端发送过来的文件

文件的"到此一游"该文件所在的路径的文件夹是个临时文件夹,运行完毕后这个文件夹里的内容清空

前端上传文件本地存储

java 复制代码
@PostMapping("/upload")
    public Result upload(String name, Integer age, MultipartFile file) throws IOException {
        // 记录接收到的参数,包括姓名、年龄和文件
        log.info("接收参数: {}, {}, {}", name, age, file);

        // 获取上传文件的原始文件名
        String originalFilename = file.getOriginalFilename();

        // 将文件保存到指定路径(D:/images/)并命名为原始文件名
        file.transferTo(new File( "D:/idea/javacode/web/Getdata/" + originalFilename));

        // 返回成功结果
        return Result.success();
    }

文件上传还存在一个要考虑的问题:如果两次提交的是不一样的文件,但是文件名称一样,那么第二次提交的图片会把第一次提交的文件给替换(覆盖)因此可以使用UUID命名来解决。

生成UUID

java 复制代码
import java.util.UUID;  

public class UUIDExample {  
    public static void main(String[] args) {  
        // 生成一个随机UUID  
        UUID uuid = UUID.randomUUID();  
        
        // 输出UUID  
        System.out.println("生成的UUID: " + uuid.toString());  
    }  
}

使用UUID解决以上问题

java 复制代码
@PostMapping("/upload")  
public Result upload(String name, Integer age, MultipartFile file) throws IOException {  
    // 记录接收到的参数,包括姓名、年龄和文件  
    log.info("接收参数: {}, {}, {}", name, age, file);  
    
    // 获取上传文件的原始文件名,例如 "1.jpg" 或 "22.2.2.2.png"  
    String originalFilename = file.getOriginalFilename();  
    
    // 获取文件扩展名,从最后一个点后开始截取  
    String extension = originalFilename.substring(originalFilename.lastIndexOf("."));  
    
    // 生成新的文件名,使用UUID并加上文件扩展名  
    String newFileName = UUID.randomUUID().toString() + extension;  
    
    // 将文件保存到指定路径(D:/images/)并命名为新的文件名  
    file.transferTo(new File("D:/images/" + newFileName));  
    
    // 返回成功结果  
    return Result.success();  
}
复制代码
file.transferTo(new File("D:/idea/javacode/web/Getdata/" + newFileName));

这个代码的路径最后一定要写个"/",使得文件保存在那个文件夹下。

上传文件大小限制

默认上传文件的最大大小为1MB,超过该大小需要在配置文件配置

java 复制代码
servlet:  
    multipart:  
# 最大单个文件大小  
        max-file-size: 10MB  
# 最大请求大小(包括所有文件和表单数据)  
        max-request-size: 100MB

阿里云OSS

阿里云对象存储oss(object Storage Service),是一款海量、安全、低成本、高可靠的云存储服务。使用oss

您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。

具体怎么配看:视频https://www.bilibili.com/video/BV1yGydYEE3H?spm_id_from=333.788.videopod.episodes&vd_source=3c46a0d84476a55380be0c2ddd012af1&p=106

配置好相关密钥等配置后,创建bucket。接下来可以通过Java代码将自己电脑本地的文件上传到阿里云。

添加好下面的依赖

XML 复制代码
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.17.4</version>
</dependency>

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

具体的上传文件的代码

java 复制代码
 public static void main(String[] args) throws com.aliyuncs.exceptions.ClientException {
        /**
         * 基础配置:连接服务并验证个人身份
         */
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-shenzhen.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "q-buckets";

        /**
         * 配置具体文件上传信息
         */
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "ph.webp"; // 可以修改名字
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
        String filePath= "D:\\Mycode\\webcode\\imag\\nu.webp";

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

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
            // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);

            // 上传文件。
            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();
            }
        }
    }

这样就可以在自己阿里云的bucket里面看到上传的文件

参考:后端之路

文件上传操作整合为工具类并在Controller中使用

具体代码如下

java 复制代码
@Component // 方便依赖注入
public class AliyunOSSOperation {  
    // 指定阿里云OSS的服务地址,这里是深圳区域的地址  
    private String endpoint = "https://oss-cn-shenzhen.aliyuncs.com";  
    // 指定要上传到的存储桶名称  
    private String bucketName = "lwq-buckets";   
    // 指定阿里云的区域,这里是深圳区域  
    private String region = "cn-shenzhen";   

    /**  
     * 上传文件到阿里云OSS  
     * @param content 文件的字节数组内容  
     * @param originalFilename 原始文件名,用于生成新的文件名  
     * @return 上传后文件的访问路径  
     * @throws Exception 可能抛出的异常  
     */  
    public String upload(byte[] content, String originalFilename) throws Exception {  
        // 从环境变量中获取访问密钥,确保在运行代码前设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET  
        EnvironmentVariableCredentialsProvider credentialsProvider =   
            CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();  
        
        // 获取object对象路径,例如2024/06/21.png。Object类型中不能包含Bucket名称  
        String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));  

        // 生成一个新的文件名,使用UUID确保唯一性,并保留原始文件的扩展名  
        String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));  
        String objectName = dir + "/" + newFileName; // 生成完整的对象名称  

        // 创建OSSClient实例  
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();  
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); // 设置签名版本为V4  

        // 使用OSSClientBuilder创建OSS客户端实例,配置包括端点、凭证提供者、客户端配置和区域  
        OSS ossClient = OSSClientBuilder.create()  
                .endpoint(endpoint)  
                .credentialsProvider(credentialsProvider)  
                .clientConfiguration(clientBuilderConfiguration)  
                .region(region)  
                .build();  

        try {  
            // 上传文件内容到指定的存储桶和对象路径  
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));  
        } finally {  
            // 确保无论上传是否成功,都会关闭OSS客户端  
            ossClient.shutdown();  
        }  

        // 生成并返回文件的完整访问路径  
        return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;  
    }  
}

使用该类

java 复制代码
@Autowired // 自动注入AliyunOSSOperator实例  
private AliyunOSSOperator aliyunOSSOperator;  

@PostMapping("/upload") // 定义一个POST请求处理方法,映射到/upload路径  
public Result upload(MultipartFile file) throws Exception {  
    // 记录上传文件的原始文件名到日志  
    log.info("文件上传: {}", file.getOriginalFilename());  
    
    // 调用aliyunOSSOperator的upload方法,将文件字节和文件名上传到OSS  
    String url = aliyunOSSOperator.upload(file.getBytes(), file.getOriginalFilename());  
    
    // 记录文件上传后返回的URL到日志  
    log.info("文件上传OSS, url: {}", url);  
    
    // 返回上传结果,包含文件的访问URL  
    return Result.success(url);  
}

这样上传到阿里云的文件以年月划分了文件夹

参数配置进一步优化

  • 指将一些需要灵活变化的参数,配置在配置文件中,然后通过 @Value 注解来注入外部配置的属性。
XML 复制代码
aliyun:  
  oss:  
    endpoint: https://oss-cn-beijing.aliyuncs.com  
    bucketName: java-ai  
    region: cn-beijing

以上配置信息配置在yml文件中
*

java 复制代码
    @Value("${aliyun.oss.endpoint}")  
    private String endpoint;  

    @Value("${aliyun.oss.bucketName}")  
    private String bucketName;  

    @Value("${aliyun.oss.region}")  
    private String region;  
相关推荐
LUCIAZZZ15 分钟前
HikariCP数据库连接池原理解析
java·jvm·数据库·spring·springboot·线程池·连接池
考虑考虑24 分钟前
Springboot3.5.x结构化日志新属性
spring boot·后端·spring
我在北京coding31 分钟前
300道GaussDB(WMS)题目及答案。
数据库·gaussdb
小Tomkk44 分钟前
阿里云 RDS mysql 5.7 怎么 添加白名单 并链接数据库
数据库·mysql·阿里云
TTDreamTT1 小时前
SpringBoot十二、SpringBoot系列web篇之过滤器Filte详解
spring boot
明月醉窗台2 小时前
qt使用笔记二:main.cpp详解
数据库·笔记·qt
沉到海底去吧Go2 小时前
【图片自动识别改名】识别图片中的文字并批量改名的工具,根据文字对图片批量改名,基于QT和腾讯OCR识别的实现方案
数据库·qt·ocr·图片识别自动改名·图片区域识别改名·pdf识别改名
老纪的技术唠嗑局2 小时前
重剑无锋,大巧不工 —— OceanBase 中的 Nest Loop Join 使用技巧分享
数据库·sql
未来之窗软件服务3 小时前
JAVASCRIPT 前端数据库-V6--仙盟数据库架构-—-—仙盟创梦IDE
数据库·数据库架构·仙盟创梦ide·东方仙盟·东方仙盟数据库
一只爱撸猫的程序猿4 小时前
构建一个简单的智能文档问答系统实例
数据库·spring boot·aigc