FastDFS快速实现和SpringBoot的整合开发

Posted 波波烤鸭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FastDFS快速实现和SpringBoot的整合开发相关的知识,希望对你有一定的参考价值。

FastDFS客户端操作

1.Fastdfs-java-client

  首先我们来看下如何实现FastDFS中提供的JavaAPI来直接实现对应的文件上传和下载操作。

1.1 文件上传

  先来看下文件上传的流程

  上传流程的文字梳理为:

  1. 客户端访问Tracker
  2. Tracker 返回Storage的ip和端口
  3. 客户端直接访问Storage,把文件内容和元数据发送过去。
  4. Storage返回文件存储id。包含了组名和文件名

  首先创建一个普通的maven项目,然后引入对应的依赖

<dependencies>
    <dependency>
        <groupId>cn.bestwu</groupId>
        <artifactId>fastdfs-client-java</artifactId>
        <version>1.27</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.4</version>
    </dependency>
</dependencies>

  然后编写FastDFS的配置文件,内容如下:注意ip修改为你自己对应的ip即可

connect_timeout = 10
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 8080
tracker_server = 192.168.56.100:22122

  然后导入对应的工具类,在工具类中完成了StorageClient的实例化,并提供了相关的上传和下载的方法。

package com.bobo.fastdfs.config;

import org.apache.commons.lang3.StringUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;

import java.io.*;

public class FastDFSClient 
    private static final String CONF_FILENAME = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";

    private static StorageClient storageClient = null;

    /**
     * 只加载一次.
     */
    static 
        try 
            ClientGlobal.init(CONF_FILENAME);
            TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
            TrackerServer trackerServer = trackerClient.getConnection();
            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            storageClient = new StorageClient(trackerServer, storageServer);
         catch (Exception e) 
            e.printStackTrace();
        
    

    /**
     *
     * @param inputStream
     *    上传的文件输入流
     * @param fileName
     *    上传的文件原始名
     * @return
     */
    public static String[] uploadFile(InputStream inputStream, String fileName) 
        try 
            // 文件的元数据
            NameValuePair[] meta_list = new NameValuePair[2];
            // 第一组元数据,文件的原始名称
            meta_list[0] = new NameValuePair("file name", fileName);
            // 第二组元数据
            meta_list[1] = new NameValuePair("file length", inputStream.available()+"");
            // 准备字节数组
            byte[] file_buff = null;
            if (inputStream != null) 
                // 查看文件的长度
                int len = inputStream.available();
                // 创建对应长度的字节数组
                file_buff = new byte[len];
                // 将输入流中的字节内容,读到字节数组中。
                inputStream.read(file_buff);
            
            // 上传文件。参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),元数据
            String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
            return fileids;
         catch (Exception ex) 
            ex.printStackTrace();
            return null;
        
    

    /**
     *
     * @param file
     *            文件
     * @param fileName
     *            文件名
     * @return 返回Null则为失败
     */
    public static String[] uploadFile(File file, String fileName) 
        FileInputStream fis = null;
        try 
            NameValuePair[] meta_list = null; // new NameValuePair[0];
            fis = new FileInputStream(file);
            byte[] file_buff = null;
            if (fis != null) 
                int len = fis.available();
                file_buff = new byte[len];
                fis.read(file_buff);
            

            String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
            return fileids;
         catch (Exception ex) 
            return null;
        finally
            if (fis != null)
                try 
                    fis.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        
    

    /**
     * 根据组名和远程文件名来删除一个文件
     *
     * @param groupName
     *            例如 "group1" 如果不指定该值,默认为group1
     * @param remoteFileName
     *            例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg"
     * @return 0为成功,非0为失败,具体为错误代码
     */
    public static int deleteFile(String groupName, String remoteFileName) 
        try 
            int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
            return result;
         catch (Exception ex) 
            return 0;
        
    

    /**
     * 修改一个已经存在的文件
     *
     * @param oldGroupName
     *            旧的组名
     * @param oldFileName
     *            旧的文件名
     * @param file
     *            新文件
     * @param fileName
     *            新文件名
     * @return 返回空则为失败
     */
    public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) 
        String[] fileids = null;
        try 
            // 先上传
            fileids = uploadFile(file, fileName);
            if (fileids == null) 
                return null;
            
            // 再删除
            int delResult = deleteFile(oldGroupName, oldFileName);
            if (delResult != 0) 
                return null;
            
         catch (Exception ex) 
            return null;
        
        return fileids;
    

    /**
     * 文件下载
     *
     * @param groupName 卷名
     * @param remoteFileName 文件名
     * @return 返回一个流
     */
    public static InputStream downloadFile(String groupName, String remoteFileName) 
        try 
            byte[] bytes = storageClient.download_file(groupName, remoteFileName);
            InputStream inputStream = new ByteArrayInputStream(bytes);
            return inputStream;
         catch (Exception ex) 
            return null;
        
    

    public static NameValuePair[] getMetaDate(String groupName, String remoteFileName)
        try
            NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
            return nvp;
        catch(Exception ex)
            ex.printStackTrace();
            return null;
        
    

    /**
     * 获取文件后缀名(不带点).
     *
     * @return 如:"jpg" or "".
     */
    private static String getFileExt(String fileName) 
        if (StringUtils.isBlank(fileName) || !fileName.contains(".")) 
            return "";
         else 
            return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
        
    



  然后我们就可以来测试上传的操作了。

    public static void main(String[] args) 
        try 
            File file = new File("D:/2.jpg");
            InputStream is = new FileInputStream(file);
            String fileName = UUID.randomUUID().toString()+".jpg";
            String[] result = FastDFSClient.uploadFile(is, fileName);
            System.out.println(Arrays.toString(result));
         catch (Exception e) 
            e.printStackTrace();
        
    

访问即可:http://192.168.56.100:8888/group1/M00/00/00/wKg4ZGHcUE6AZA2UAAW8dIX5p50374.jpg

  返回后的字符串的结构说明

1.2 文件下载

  文件下载的流程,如下

  文件下载的流程为:

  1. client询问tracker需要下载的文件的storage,参数为文件的标识(group加文件名)。
  2. tracker根据客户端的参数返回一台可用的storage。
  3. client根据返回的storage直接完成对应的文件的下载。

  有了上面的基础,文件下载就非常简单了,我们只需要根据前面上传的文件的group和文件的存储路径就可以通过StorageClient中提供的downloadFile方法把对应的文件下载下来了,具体的代码如下

    /**
     * 文件下载
     */
    public static void downloadFile()
        try 
            InputStream is = FastDFSClient
                    .downloadFile("group1", "M00/00/00/wKg4ZGHcUE6AZA2UAAW8dIX5p50374.jpg");
            OutputStream os = new FileOutputStream(new File("D:/12.jpg"));
            int index = 0 ;
            while((index = is.read())!=-1)
                os.write(index);
            
            os.flush();
            os.close();
            is.close();
         catch (Exception e) 
            e.printStackTrace();
        
    

2.SpringBoot整合

  我们在实际工作中基本都是和SpringBoot整合在一起来使用的,那么我们就来看看FastDFS是如何在SpringBoot项目中来使用的。首先创建一个普通的SpringBoot项目,然后导入fastdfs-spring-boot-starter这个依赖。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.luhuiguo</groupId>
            <artifactId>fastdfs-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>
    </dependencies>

  既然是一个starter,那么必然会在spring.factories文件中提供对应的自动配置类。

  可以看到给我们提供的配置类为FdfsAutoConfiguration进入后可以看到帮我们注入了很多的核心对象。

  然后可以看到系统提供的配置信息,前缀为 fdfs

  然后我们就可以在application.properties中配置FastDFS的配置信息了。

  配置完成后我们就可以测试文件的上传下载操作了

@SpringBootTest
class FastDfsSpringBootApplicationTests 

    @Autowired
    public FastFileStorageClient storageClient;


    @Test
    void contextLoads() throws Exception
        File file = new File("d:\\\\2.jpg");
        StorePath path = storageClient.uploadFile(null,new FileInputStream(file),file.length(),file.getName());
        System.out.println(path.getFullPath());
    


文件操作成功

以上是关于FastDFS快速实现和SpringBoot的整合开发的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot整合FastDFS实现文件的上传下载和删除

SpringBoot项目整合FastDFS+Nginx实现图片上传

SpringBoot2.0集成FastDFS

SpringBoot集成FastDFS+Nginx整合基于Token的防盗链

SpringBoot实现上传文件到fastDFS文件服务器

FastDFS整合SpringBoot