Minio+Vue+Springboot:网页文件上传-对象文件存储实战

一、场景分析

技术架构

  1. 前端:Vue + Axios
  2. 后端:Spring Boot
  3. 存储:MinIO对象存储

实现步骤

1. Spring Boot配置

在application.yml中添加MinIO配置:

yaml 复制代码
minio:
  url: http://localhost:9000
  access-key: your-access-key
  secret-key: your-secret-key
  bucket-name: mybucket
  secure: false

2. 文件上传实现

前端核心代码:

html 复制代码
<template>
  <div>
    <input type="file" @change="handleFileUpload">
    <button @click="uploadFile">上传</button>
    <div v-if="progress > 0">进度:{{progress}}%</div>
  </div>
</template>

3. 后端处理逻辑

使用MinIO Java Client实现文件存储:

  • 自动创建存储桶
  • 支持多种文件类型
  • 返回可访问URL

最佳实践

  1. 文件命名使用UUID避免重复
  2. 限制上传文件大小
  3. 前端添加文件类型校验
  4. 后端配置CORS策略

二、前端代码(Vue实现)

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>文件上传</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
    <div id="app">
        <div>
            <input type="file" ref="fileInput" @change="onFileSelect">
            <button @click="upload">上传文件</button>
            <div v-if="uploadProgress > 0">
                上传进度:{{ uploadProgress }}%
            </div>
            <div v-if="fileUrl">
                文件地址:<a :href="fileUrl" target="_blank">{{ fileUrl }}</a>
            </div>
        </div>
    </div>

    <script>
        const { createApp } = Vue;
        
        createApp({
            data() {
                return {
                    selectedFile: null,
                    uploadProgress: 0,
                    fileUrl: ''
                };
            },
            methods: {
                onFileSelect(event) {
                    this.selectedFile = event.target.files[0];
                },
                async upload() {
                    if (!this.selectedFile) return;
                    
                    const formData = new FormData();
                    formData.append('file', this.selectedFile);
                    
                    try {
                        const response = await axios.post('/api/upload', formData, {
                            headers: { 'Content-Type': 'multipart/form-data' },
                            onUploadProgress: (progressEvent) => {
                                this.uploadProgress = Math.round(
                                    (progressEvent.loaded * 100) / progressEvent.total
                                );
                            }
                        });
                        
                        this.fileUrl = response.data.url;
                        alert('上传成功!');
                    } catch (error) {
                        console.error('上传失败:', error);
                        alert('上传失败!');
                    }
                }
            }
        }).mount('#app');
    </script>
</body>
</html>

三、Spring Boot配置

application.yml配置示例:

yaml 复制代码
server:
  port: 8080

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

minio:
  url: http://localhost:9000
  access-key: minioadmin
  secret-key: minioadmin
  bucket-name: mybucket
  secure: false

四、后端Java代码

FileStorageController.java:

java 复制代码
@RestController
@RequestMapping("/api")
public class FileStorageController {

    @Autowired
    private FileStorageService fileStorageService;

    @PostMapping("/upload")
    public ResponseEntity<Map<String, String>> uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            String url = fileStorageService.uploadFile(file);
            return ResponseEntity.ok().body(Collections.singletonMap("url", url));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(Collections.singletonMap("error", e.getMessage()));
        }
    }
}

FileStorageService.java:

java 复制代码
@Service
public class FileStorageService {

    @Value("${minio.url}")
    private String minioUrl;
    
    @Value("${minio.access-key}")
    private String accessKey;
    
    @Value("${minio.secret-key}")
    private String secretKey;
    
    @Value("${minio.bucket-name}")
    private String bucketName;

    private MinioClient minioClient;

    @PostConstruct
    public void init() throws Exception {
        minioClient = MinioClient.builder()
                .endpoint(minioUrl)
                .credentials(accessKey, secretKey)
                .build();
                
        createBucketIfNotExists();
    }

    private void createBucketIfNotExists() throws Exception {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder()
                .bucket(bucketName)
                .build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        }
    }

    public String uploadFile(MultipartFile file) throws Exception {
        String fileName = UUID.randomUUID() + "-" + file.getOriginalFilename();
        
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build());
                
        return minioUrl + "/" + bucketName + "/" + fileName;
    }
}

五、系统要求

  1. 添加MinIO Java客户端依赖(pom.xml):
xml 复制代码
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.5.6</version>
</dependency>
  1. 启动MinIO服务:
bash 复制代码
minio server /data --console-address ":9001"

该方案实现了:

  1. 前端文件上传进度显示
  2. 自动生成唯一文件名
  3. 支持多种文件类型
  4. 返回可直接访问的URL
  5. 完善的异常处理机制

建议根据实际需求添加:

  1. 文件类型白名单校验
  2. 文件大小限制
  3. 用户身份验证
  4. 文件管理功能(删除、列表等)
相关推荐
codingandsleeping29 分钟前
Express入门
javascript·后端·node.js
ss2731 小时前
基于Springboot + vue + 爬虫实现的高考志愿智能推荐系统
spring boot·后端·高考
专注API从业者2 小时前
《Go 语言高并发爬虫开发:淘宝商品 API 实时采集与 ETL 数据处理管道》
开发语言·后端·爬虫·golang
Asthenia04122 小时前
Netty writeAndFlush与Pipeline深入分析
后端
欧先生^_^2 小时前
Scala语法基础
开发语言·后端·scala
GetcharZp3 小时前
xterm.js 终端神器到底有多强?用了才知道!
前端·后端·go
洞窝技术4 小时前
MYSQL:关于索引你想知道的
后端·mysql
MrWho不迷糊4 小时前
企业级权限系统怎么设计四 —— ABAC模型统一功能权限与数据权限
后端·微服务
落尘2984 小时前
Spring MVC——传递参数的方式
后端
ITCharge4 小时前
Docker 万字教程:从入门到掌握
后端·docker·容器