• 分布式文件存储系统FastDFS[2]-上传和下载文件工具类


    一、文件上传流程

    1 时序图

    2 流程说明

    1. 客户端访问Tracker

    2. Tracker 返回Storage的ip和端口

    3. 客户端直接访问Storage,把文件内容和元数据发送过去。

    4. Storage返回文件存储id。包含了组名和文件名

    1 添加依赖

    1. <dependencies>
    2.   <dependency>
    3.       <groupId>cn.bestwugroupId>
    4.       <artifactId>fastdfs-client-javaartifactId>
    5.       <version>1.27version>
    6.   dependency>
    7.   <dependency>
    8.       <groupId>org.apache.commonsgroupId>
    9.       <artifactId>commons-lang3artifactId>
    10.       <version>3.4version>
    11.   dependency>
    12. dependencies> `

    2 编写配置文件

    文件名:fdfs_client.conf

    修改成自己的tracker服务器ip

    1. connect_timeout = 10
    2. network_timeout = 30
    3. charset = UTF-8
    4. http.tracker_http_port = 8080
    5. tracker_server = 192.168.93.10:22122  

    3 导入工具类

    在com.utils.FastDFSClient 下粘贴配置工具类

    1. package com.msb.utils;
    2. import java.io.ByteArrayInputStream;
    3. import java.io.File;
    4. import java.io.FileInputStream;
    5. import java.io.IOException;
    6. import java.io.InputStream;
    7. import org.apache.commons.lang3.StringUtils;
    8. import org.csource.common.NameValuePair;
    9. import org.csource.fastdfs.ClientGlobal;
    10. import org.csource.fastdfs.StorageClient;
    11. import org.csource.fastdfs.StorageClient1;
    12. import org.csource.fastdfs.StorageServer;
    13. import org.csource.fastdfs.TrackerClient;
    14. import org.csource.fastdfs.TrackerServer;
    15. /**
    16. * FastDFS分布式文件系统操作客户端.
    17. */
    18. public class FastDFSClient {
    19. private static final String CONF_FILENAME = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";
    20. private static StorageClient storageClient = null;
    21. /**
    22. * 只加载一次.
    23. */
    24. static {
    25. try {
    26. ClientGlobal.init(CONF_FILENAME);
    27. TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
    28. TrackerServer trackerServer = trackerClient.getConnection();
    29. StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
    30. storageClient = new StorageClient(trackerServer, storageServer);
    31. } catch (Exception e) {
    32. e.printStackTrace();
    33. }
    34. }
    35. /**
    36. *
    37. * @param inputStream
    38. * 上传的文件输入流
    39. * @param fileName
    40. * 上传的文件原始名
    41. * @return
    42. */
    43. public static String[] uploadFile(InputStream inputStream, String fileName) {
    44. try {
    45. // 文件的元数据
    46. NameValuePair[] meta_list = new NameValuePair[2];
    47. // 第一组元数据,文件的原始名称
    48. meta_list[0] = new NameValuePair("file name", fileName);
    49. // 第二组元数据
    50. meta_list[1] = new NameValuePair("file length", inputStream.available()+"");
    51. // 准备字节数组
    52. byte[] file_buff = null;
    53. if (inputStream != null) {
    54. // 查看文件的长度
    55. int len = inputStream.available();
    56. // 创建对应长度的字节数组
    57. file_buff = new byte[len];
    58. // 将输入流中的字节内容,读到字节数组中。
    59. inputStream.read(file_buff);
    60. }
    61. // 上传文件。参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),元数据
    62. String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
    63. return fileids;
    64. } catch (Exception ex) {
    65. ex.printStackTrace();
    66. return null;
    67. }
    68. }
    69. /**
    70. *
    71. * @param file
    72. * 文件
    73. * @param fileName
    74. * 文件名
    75. * @return 返回Null则为失败
    76. */
    77. public static String[] uploadFile(File file, String fileName) {
    78. FileInputStream fis = null;
    79. try {
    80. NameValuePair[] meta_list = null; // new NameValuePair[0];
    81. fis = new FileInputStream(file);
    82. byte[] file_buff = null;
    83. if (fis != null) {
    84. int len = fis.available();
    85. file_buff = new byte[len];
    86. fis.read(file_buff);
    87. }
    88. String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
    89. return fileids;
    90. } catch (Exception ex) {
    91. return null;
    92. }finally{
    93. if (fis != null){
    94. try {
    95. fis.close();
    96. } catch (IOException e) {
    97. e.printStackTrace();
    98. }
    99. }
    100. }
    101. }
    102. /**
    103. * 根据组名和远程文件名来删除一个文件
    104. *
    105. * @param groupName
    106. * 例如 "group1" 如果不指定该值,默认为group1
    107. * @param remoteFileName
    108. * 例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg"
    109. * @return 0为成功,非0为失败,具体为错误代码
    110. */
    111. public static int deleteFile(String groupName, String remoteFileName) {
    112. try {
    113. int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
    114. return result;
    115. } catch (Exception ex) {
    116. return 0;
    117. }
    118. }
    119. /**
    120. * 修改一个已经存在的文件
    121. *
    122. * @param oldGroupName
    123. * 旧的组名
    124. * @param oldFileName
    125. * 旧的文件名
    126. * @param file
    127. * 新文件
    128. * @param fileName
    129. * 新文件名
    130. * @return 返回空则为失败
    131. */
    132. public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) {
    133. String[] fileids = null;
    134. try {
    135. // 先上传
    136. fileids = uploadFile(file, fileName);
    137. if (fileids == null) {
    138. return null;
    139. }
    140. // 再删除
    141. int delResult = deleteFile(oldGroupName, oldFileName);
    142. if (delResult != 0) {
    143. return null;
    144. }
    145. } catch (Exception ex) {
    146. return null;
    147. }
    148. return fileids;
    149. }
    150. /**
    151. * 文件下载
    152. *
    153. * @param groupName 卷名
    154. * @param remoteFileName 文件名
    155. * @return 返回一个流
    156. */
    157. public static InputStream downloadFile(String groupName, String remoteFileName) {
    158. try {
    159. byte[] bytes = storageClient.download_file(groupName, remoteFileName);
    160. InputStream inputStream = new ByteArrayInputStream(bytes);
    161. return inputStream;
    162. } catch (Exception ex) {
    163. return null;
    164. }
    165. }
    166. public static NameValuePair[] getMetaDate(String groupName, String remoteFileName){
    167. try{
    168. NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
    169. return nvp;
    170. }catch(Exception ex){
    171. ex.printStackTrace();
    172. return null;
    173. }
    174. }
    175. /**
    176. * 获取文件后缀名(不带点).
    177. *
    178. * @return 如:"jpg" or "".
    179. */
    180. private static String getFileExt(String fileName) {
    181. if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
    182. return "";
    183. } else {
    184. return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
    185. }
    186. }
    187. }

    4 编写测试代码

    随意新建一个包含主方法的类。com.msb.MyMain

    1. public class MyMain {
    2.   public static void main(String[] args) {
    3.       try {
    4.           File file = new File("D:/b.png");
    5.           InputStream is = new FileInputStream(file);
    6.           String fileName = UUID.randomUUID().toString()+".png";
    7.           String[] result = FastDFSClient.uploadFile(is, fileName);
    8.           System.out.println(Arrays.toString(result));
    9.       } catch (FileNotFoundException e) {
    10.           e.printStackTrace();
    11.       }
    12.   }
    13. }  

    二、文件下载

     

    2 下载说明

    1. client询问tracker下载文件的storage,参数为文件标识(组名和文件名);

    2. tracker返回一台可用的storage;

    3. client直接和storage通讯完成文件下载。

    3 代码实现

    直接使用工具方法完成下载。

    1. try {
    2.   InputStream is = FastDFSClient.downloadFile("group1", "M00/00/00/wKg0gF3zAKCARs6kAAASjQVYlWA098.png");
    3.   OutputStream os = new FileOutputStream(new File("D:/jqk.png"));
    4.   int index = 0 ;
    5.   while((index = is.read())!=-1){
    6.       os.write(index);
    7.   }
    8.   os.flush();
    9.   os.close();
    10.   is.close();
    11. } catch (IOException e) {
    12.   e.printStackTrace();
    13. }

  • 相关阅读:
    VMware下Linux虚拟机挂载Windows共享文件夹
    Linux命令基本用法
    “数聚瑞安·创新未来”中国·瑞安第四届创新创业大赛圆满举办!
    Taurus .Net Core 微服务开源框架:Admin 插件【3】 - 指标统计管理 -【API、Redis、MemCache】
    “碳”零排放是什么意思
    Python 变量的定义和数据类型的转换
    linux离线环境安装redis
    好马配好鞍:Linux Kernel 4.12 正式发布
    开机优化加速
    域内路由选择协议——RIP
  • 原文地址:https://blog.csdn.net/listeningdu/article/details/128211775