x-file-storage
Java 中使用 X-File-Storage
官方地址:https://x-file-storage.xuyanwu.cn/#/
一行代码将文件存储到本地、FTP、SFTP、WebDAV、阿里云 OSS、华为云 OBS、七牛云 Kodo、腾讯云 COS、百度云 BOS、又拍云 USS、MinIO、 Amazon S3、GoogleCloud Storage、FastDFS、 Azure Blob Storage、Cloudflare R2、金山云 KS3、美团云 MSS、京东云 OSS、天翼云 OOS、移动 云EOS、沃云 OSS、 网易数帆 NOS、Ucloud US3、青云 QingStor、平安云 OBS、首云 OSS、IBM COS、其它兼容 S3 协议的存储平台。
1. 添加依赖
首先需要在项目中添加 X-File-Storage 的依赖:
<!-- Maven 依赖 -->
<dependency><groupId>org.x-file-storage</groupId><artifactId>x-file-storage-core</artifactId><version>最新版本</version> <!-- 如 1.2.0 -->
</dependency><!-- 如果需要 Spring Boot 支持 -->
<dependency><groupId>org.x-file-storage</groupId><artifactId>x-file-storage-spring-boot-starter</artifactId><version>最新版本</version>
</dependency>
2. 基本配置
2.1 Spring Boot 配置
# application.yml
x-file-storage:default-platform: local-1 # 默认使用的存储平台thumbnail-suffix: ".min.jpg" # 缩略图后缀platforms:local-1: # 本地存储enable: trueenable-storage: truebase-path: /data/file/ # 存储根目录domain: http://localhost:8080/file/ # 访问域名aliyun-oss-1: # 阿里云OSSenable: trueenable-storage: trueaccess-key: your-access-keysecret-key: your-secret-keyend-point: oss-cn-hangzhou.aliyuncs.combucket-name: your-bucketdomain: https://your-bucket.oss-cn-hangzhou.aliyuncs.com # 访问域名
2.2 非 Spring 项目配置
// 创建本地存储服务
LocalFileStorage localStorage = new LocalFileStorage();
localStorage.setBasePath("/data/file/");
localStorage.setPlatform("local-1");// 创建阿里云OSS存储服务
AliyunOssFileStorage ossStorage = new AliyunOssFileStorage();
ossStorage.setPlatform("aliyun-oss-1");
ossStorage.setAccessKey("your-access-key");
ossStorage.setSecretKey("your-secret-key");
ossStorage.setEndPoint("oss-cn-hangzhou.aliyuncs.com");
ossStorage.setBucketName("your-bucket");// 创建文件存储管理器
FileStorageService fileStorageService = new FileStorageServiceBuilder().addFileStorage(localStorage).addFileStorage(ossStorage).build();
3. 基本使用
3.1 文件上传
// 自动注入文件存储服务
@Autowired
private FileStorageService fileStorageService;// 上传文件
public void uploadFile() throws IOException {// 方式1:使用File对象上传File file = new File("test.jpg");FileInfo fileInfo = fileStorageService.of(file).setPlatform("aliyun-oss-1") // 指定存储平台.setPath("images/") // 存储路径.setOriginalFilename("test.jpg") // 原始文件名.upload();// 方式2:使用InputStream上传InputStream inputStream = new FileInputStream("test.jpg");FileInfo fileInfo2 = fileStorageService.of(inputStream).setPlatform("local-1").setPath("temp/").setFilename("test2.jpg") // 存储文件名.setContentType("image/jpeg") // 设置MIME类型.putAttr("user","123") // 添加附加属性.upload();System.out.println("文件上传成功:" + fileInfo.getUrl());
}
3.2 文件下载
// 下载文件到本地
public void downloadFile() {String url = "http://your-bucket.oss-cn-hangzhou.aliyuncs.com/images/test.jpg";// 方式1:下载到文件fileStorageService.download(url).file("downloaded.jpg");// 方式2:获取InputStreamInputStream inputStream = fileStorageService.download(url).inputStream();// 处理输入流...// 方式3:获取字节数组byte[] bytes = fileStorageService.download(url).bytes();
}
3.3 文件管理
// 获取文件信息
public void getFileInfo() {String url = "http://your-bucket.oss-cn-hangzhou.aliyuncs.com/images/test.jpg";FileInfo fileInfo = fileStorageService.getFileInfoByUrl(url);System.out.println("文件大小:" + fileInfo.getSize());System.out.println("文件类型:" + fileInfo.getContentType());
}// 删除文件
public void deleteFile() {String url = "http://your-bucket.oss-cn-hangzhou.aliyuncs.com/images/test.jpg";boolean deleted = fileStorageService.delete(url);System.out.println("删除结果:" + deleted);
}// 判断文件是否存在
public void existsFile() {String url = "http://your-bucket.oss-cn-hangzhou.aliyuncs.com/images/test.jpg";boolean exists = fileStorageService.exists(url);System.out.println("文件是否存在:" + exists);
}
4. 高级功能
4.1 缩略图生成
// 上传时生成缩略图
public void uploadWithThumbnail() throws IOException {FileInfo fileInfo = fileStorageService.of(new File("test.jpg")).setThumbnailSuffix(".min.jpg") // 缩略图后缀.setSaveThumbnail(true) // 是否保存缩略图.thumbnail(200, 200) // 缩略图尺寸.upload();System.out.println("缩略图URL:" + fileInfo.getThumbnailUrl());
}// 对已有文件生成缩略图
public void generateThumbnail() {String url = "http://your-bucket.oss-cn-hangzhou.aliyuncs.com/images/test.jpg";FileInfo thumbnailInfo = fileStorageService.generateThumbnail(url, 200, 200);System.out.println("缩略图URL:" + thumbnailInfo.getUrl());
}
4.2 文件复制与移动
// 复制文件
public void copyFile() {String sourceUrl = "http://your-bucket.oss-cn-hangzhou.aliyuncs.com/images/test.jpg";String targetUrl = fileStorageService.copy(sourceUrl).setPlatform("local-1").setPath("backup/").copy();System.out.println("复制后的文件URL:" + targetUrl);
}// 移动/重命名文件
public void moveFile() {String sourceUrl = "http://your-bucket.oss-cn-hangzhou.aliyuncs.com/images/test.jpg";String targetUrl = fileStorageService.move(sourceUrl).setPath("new-images/").setFilename("new-name.jpg").move();System.out.println("移动后的文件URL:" + targetUrl);
}
4.3 文件分片上传
// 分片上传大文件
public void multipartUpload() throws IOException {File file = new File("large-file.zip");String uploadId = fileStorageService.initiateMultipartUpload(file.length(), "large-file.zip");// 模拟分片上传int partSize = 5 * 1024 * 1024; // 5MBbyte[] buffer = new byte[partSize];try (InputStream in = new FileInputStream(file)) {int partNumber = 1;while (true) {int bytesRead = in.read(buffer);if (bytesRead == -1) break;byte[] partData = Arrays.copyOf(buffer, bytesRead);fileStorageService.uploadPart(uploadId, partNumber, partData);partNumber++;}}// 完成分片上传FileInfo fileInfo = fileStorageService.completeMultipartUpload(uploadId);System.out.println("大文件上传完成:" + fileInfo.getUrl());
}
5. 最佳实践
- 异常处理:所有文件操作都应该捕获
FileStorageException
try {fileStorageService.upload(...);
} catch (FileStorageException e) {// 处理文件存储异常logger.error("文件上传失败", e);
}
- 使用监听器:可以添加上传下载的监听器
fileStorageService.setUploadListener(new UploadListener() {@Overridepublic void start(UploadPretreatment pre) {System.out.println("开始上传:" + pre.getOriginalFilename());}@Overridepublic void success(FileInfo fileInfo) {System.out.println("上传成功:" + fileInfo.getUrl());}@Overridepublic void failure(FileInfo fileInfo, Exception e) {System.out.println("上传失败:" + fileInfo.getOriginalFilename());}
});
- 自定义存储平台:可以通过实现
FileStorage
接口扩展自己的存储平台
public class MyCustomStorage implements FileStorage {// 实现必要的方法
}// 注册自定义存储
fileStorageService.addFileStorage(new MyCustomStorage());
6 案例
1)在pom.xml中引入依赖
<!-- 文件上传-->
<dependency><groupId>org.dromara.x-file-storage</groupId><artifactId>x-file-storage-spring</artifactId><version>2.1.0</version></dependency><!-- 阿里云oss-->
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.16.1</version></dependency>
2)在application.yml 配置文件中先添加以下基础配置,再添加对应平台的配置
# 文件上传
dromara:x-file-storage: #文件存储配置default-platform: aliyun-oss-1 #默认使用的存储平台thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】#对应平台的配置写在这里,注意缩进要对齐aliyun-oss:- platform: aliyun-oss-1 # 存储平台标识enable-storage: true # 启用存储access-key: ??secret-key: ??end-point: ??bucket-name: ??domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/base-path: dkd-images/ # 基础路径
3)在的启动类上加上@EnableFileStorage注解
@EnableFileStorage
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class DkdApplication
{public static void main(String[] args){// System.setProperty("spring.devtools.restart.enabled", "false");SpringApplication.run(DkdApplication.class, args);}
}
4)修改单个文件上传的方法
@Autowired
private FileStorageService fileStorageService;//注入实列/*** 通用上传请求(单个)
*/
@PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception {try {// 指定oss保存文件路径String objectName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) + "/";// 上传图片,成功返回文件信息FileInfo fileInfo = fileStorageService.of(file).setPath(objectName).upload();// 设置返回结果AjaxResult ajax = AjaxResult.success();ajax.put("url", fileInfo.getUrl());ajax.put("fileName", fileInfo.getUrl()); //注意:这里的值要改为url,前端访问的地址,需要文件的地址 而不是文件名称ajax.put("newFileName", fileInfo.getUrl());ajax.put("originalFilename", file.getOriginalFilename());return ajax;} catch (Exception e) {return AjaxResult.error(e.getMessage());}
}