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

发布于:2024-12-21 ⋅ 阅读:(9) ⋅ 点赞:(0)

 上传文件的基本操作

<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接收前端发来的文件

@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

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

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

 前端上传文件本地存储

@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

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解决以上问题
 

@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,超过该大小需要在配置文件配置

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

阿里云OSS

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

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

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

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

添加好下面的依赖

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

 具体的上传文件的代码

 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中使用

具体代码如下

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

使用该类 

@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 注解来注入外部配置的属性。
  • aliyun:  
      oss:  
        endpoint: https://oss-cn-beijing.aliyuncs.com  
        bucketName: java-ai  
        region: cn-beijing

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

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