Java 客户端操作 FastDFS 实现文件上传下载替换删除

  FastDFS 的作者余庆先生已经为我们开发好了 Java 对应的 SDK。这里需要解释一下:作者余庆并没有及时更新最新的 Java SDK 至 Maven 中央仓库,目前中央仓库最新版仍旧是 1.27 版。所以我们需要通过 Github:https://github.com/happyfish100/fastdfs-client-java 下载项目源码,再通过命令 mvn clean install 编译打包导入 Maven 本地仓库使用即可。

  接下来我们通过 Java API 操作 FastDFS 实现文件的上传、下载、替换、删除、查询元数据、查询详情等功能。

  文中案例已同步至:

  

1|0创建项目

  

  

2|0添加依赖

  

  在项目的 pom.xml 中添加以下依赖。因为我们需要一些常用工具包和单元测试,所以需要引入它们。

<!-- fastdfs java client --> <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.29-SNAPSHOT</version> </dependency> <!-- apache commons lang3 工具包 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.11</version> </dependency> <!-- junit 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency>

  

3|0编写配置文件

  

  fdfs_client.conf

# 超时时间 connect_timeout = 10 network_timeout = 30 # 编码字符集 charset = UTF-8 # tracker 服务器 HTTP 协议下暴露的端口 http.tracker_http_port = 8080 # tracker 服务器的 IP 和端口 tracker_server = 192.168.10.101:22122

  

4|0工具类

  

package org.example.client; import org.apache.commons.lang3.StringUtils; import org.csource.common.MyException; import org.csource.common.NameValuePair; import org.csource.fastdfs.*; import java.io.*; /** * FastDFS 分布式文件系统 Java 客户端工具类 * 具体功能:文件上传、下载、替换、删除、查询文件元数据、查看文件详情 */ public class FastDFSClient { // 获取配置文件地址 private static final String CONF_FILENAME = Thread.currentThread() .getContextClassLoader().getResource("").getPath() + "fdfs_client.conf"; // Storage 存储服务器客户端 private static StorageClient storageClient = null; static { try { // 加载配置文件 ClientGlobal.init(CONF_FILENAME); // 初始化 Tracker 客户端 TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group); // 初始化 Tracker 服务端 TrackerServer trackerServer = trackerClient.getTrackerServer(); // 初始化 Storage 服务端 StorageServer storageServer = trackerClient.getStoreStorage(trackerServer); // 初始化 Storage 客户端 storageClient = new StorageClient(trackerServer, storageServer); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } } /** * 文件上传 * * @param inputStream 上传的文件的字节输入流 * @param fileName 上传的文件的原始名 * @return */ public static String[] uploadFile(InputStream inputStream, String fileName) { try { // 准备字节数组 byte[] fileBuff = null; // 文件元数据 NameValuePair[] metaList = null; if (inputStream != null) { // 查看文件的长度 int len = inputStream.available(); // 初始化元数据数组 metaList = new NameValuePair[2]; // 第一组元数据,文件的原始名称 metaList[0] = new NameValuePair("file_name", fileName); // 第二组元数据,文件的长度 metaList[1] = new NameValuePair("file_length", String.valueOf(len)); // 创建对应长度的字节数组 fileBuff = new byte[len]; // 将输入流中的字节内容,读到字节数组中 inputStream.read(fileBuff); } /* 上传文件。 参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),元数据 */ String[] fileids = storageClient.upload_file(fileBuff, getFileExt(fileName), metaList); return fileids; } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; } /** * 文件上传 * * @param file 上传的文件 * @param fileName 上传的文件的原始名 * @return */ public static String[] uploadFile(File file, String fileName) { try (FileInputStream fis = new FileInputStream(file)) { return uploadFile(fis, fileName); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 获取文件后缀名(不带点) * * @param fileName * @return 如:"jpg" or "" */ private static String getFileExt(String fileName) { if (StringUtils.isBlank(fileName) || !fileName.contains(".")) { return ""; } return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点 } /** * 获取文件详情 * * @param groupName 组/卷名,默认值:group1 * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg" * @return 文件详情 */ public static FileInfo getFileInfo(String groupName, String remoteFileName) { try { return storageClient.get_file_info(groupName == null ? "group1" : groupName, remoteFileName); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; } /** * 获取元数据 * * @param groupName 组/卷名,默认值:group1 * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg" * @return 文件的元数据数组 */ public static NameValuePair[] getMetaData(String groupName, String remoteFileName) { try { // 根据组名和文件名通过 Storage 客户端获取文件的元数据数组 return storageClient.get_metadata(groupName == null ? "group1" : groupName, remoteFileName); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; } /** * 文件下载 * * @param groupName 组/卷名,默认值:group1 * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg" * @return 文件的字节输入流 */ public static InputStream downloadFile(String groupName, String remoteFileName) { try { // 根据组名和文件名通过 Storage 客户端获取文件的字节数组 byte[] bytes = storageClient.download_file(groupName == null ? "group1" : groupName, remoteFileName); // 返回字节流对象 InputStream inputStream = new ByteArrayInputStream(bytes); return inputStream; } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; } /** * 文件删除 * * @param groupName 组/卷名,默认值:group1 * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg" * @return 0为成功,非0为失败 */ public static int deleteFile(String groupName, String remoteFileName) { int result = -1; try { // 根据组名和文件名通过 Storage 客户端删除文件 result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return result; } /** * 修改一个已经存在的文件 * * @param oldGroupName 旧组名 * @param oldFileName 旧文件名 * @param file 新文件 * @param fileName 新文件名 * @return */ public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) { // 先上传 String[] fileids = uploadFile(file, fileName); if (fileids == null) { return null; } // 再删除 int delResult = deleteFile(oldGroupName, oldFileName); if (delResult != 0) { return null; } return fileids; } }

  

5|0测试

  

5|1文件上传

  

// 文件上传 @Test public void testUploadFile() { String[] fileids = FastDFSClient.uploadFile(new File("D:/china.jpg"), "china.jpg"); for (String fileid : fileids) { System.out.println("fileid = " + fileid); } }

  返回值:

fileid = group1 fileid = M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg

  

5|2文件详情

  

// 查看文件详情 @Test public void testGetFileInfo() { FileInfo fileInfo = FastDFSClient.getFileInfo("group1", "M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg"); System.out.println("fileInfo = " + fileInfo); }

  返回值:

fileInfo = fetch_from_server = false, file_type = 1, source_ip_addr = 192.168.10.102, file_size = 57704, create_timestamp = 2020-09-28 08:44:08, crc32 = 645874781

  

5|3文件元数据

  

// 获取文件数据 @Test public void testGetMetaData() { NameValuePair[] metaDatas = FastDFSClient.getMetaData("group1", "M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg"); for (NameValuePair metaData : metaDatas) { System.out.println(metaData.getName() + "---" + metaData.getValue()); } }

  返回值:

file_length---57704 file_name---china.jpg

  

5|4文件下载

  

// 文件下载 @Test public void testDownloadFile() { InputStream is = FastDFSClient.downloadFile("group1", "M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg"); try (FileOutputStream fos = new FileOutputStream("D:/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg")) { int len = 0; byte[] bytes = new byte[1024]; while ((len = is.read(bytes)) != -1) { fos.write(bytes, 0, len); fos.flush(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

  

5|5文件删除

  

// 文件删除 @Test public void testDeleteFile() { int result = FastDFSClient.deleteFile("group1", "M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg"); System.out.println("result = " + result); }

  返回值:

result = 0

  

5|6文件替换

  

// 文件替换 @Test public void testModifyFile() { String[] fileids = FastDFSClient.modifyFile("group1", "M00/00/00/wKgKZl9xOS2ASdu8AADhaCZ_RF0898.jpg", new File("D:/mhw.jpg"), "mhw.jpg"); for (String fileid : fileids) { System.out.println("fileid = " + fileid); } }

  返回值:

fileid = group1 fileid = M00/00/00/wKgKZl9xOeaAFO00AACmo7QBGtA298.jpg

  至此 Java 客户端操作 FastDFS 实现文件上传下载替换删除等操作就到这里,下一篇我们带大家搭建 FastDFS 的集群环境,多 Tracker 多 Storage 然后通过 Nginx 代理。

本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议

大家可以通过 分类 查看更多关于 FastDFS 的文章。

  

🤗 您的点赞转发是对我最大的支持。

📢 关注公众号 哈喽沃德先生「文档 + 视频」每篇文章都配有专门视频讲解,学习更轻松噢 ~


__EOF__

本文作者哈喽沃德先生
本文链接https://www.cnblogs.com/mrhelloworld/p/fastdfs-java.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   哈喽沃德先生  阅读(2896)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示