FastDFS Learning-SpringBoot Integrated FastDFS

Posted by karq on Tue, 06 Aug 2019 10:04:29 +0200

Relevant dependency

<!-- https://mvnrepository.com/artifact/net.oschina.zcx7878/fastdfs-client-java -->
<dependency>
   <groupId>net.oschina.zcx7878</groupId>
   <artifactId>fastdfs-client-java</artifactId>
   <version>1.27.0.0</version>
</dependency>

FastDFS Upload Client Tool Class

/**
 * FastDFS File System Client
 * @author: Kellan_Song
 * @date: 2019-08-04 21:12
 **/
@Component
public class FastDFSClient {
    
     private final String GROUP_NAME = "group1"; //Group name
    private TrackerClient trackerClient; 
    private TrackerServer trackerServer;
    private StorageServer storageServer;
    private StorageClient storageClient;

    public FastDFSClient() throws Exception {
        ClientGlobal.initByTrackers("193.112.40.54:22122");
        trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
        trackerServer = trackerClient.getConnection();
        storageServer = trackerClient.getStoreStorage(trackerServer);
        storageClient = new StorageClient(trackerServer, storageServer);
    }

    /**
     * Upload files
     * @param file File object
     * @param fileName file name
     * @return
     */
    public  String[] uploadFile(File file, String fileName) {
        try {
            byte[] buff = IOUtils.toByteArray(new FileInputStream(file));
            return uploadFile(buff, fileName, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Upload files
     * @param buff File stream
     * @param fileName file name
     * @return
     */
    public  String[] uploadFile(byte[] buff, String fileName) {
        return uploadFile(buff, fileName, null);
    }

    /**
     * Upload files
     * @param file file
     * @return
     */
    public  String[] uploadFile(MultipartFile file) {
        try {
            return uploadFile(file.getBytes(), file.getOriginalFilename(), null);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Upload files
     *
     * @param buff     File stream
     * @param fileName file name
     * @param metaList meta-data
     * @return
     */
    public  String[] uploadFile(byte[] buff, String fileName, Map<String,String> metaList) {
        String prefix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()); // File suffix name
        try {
            NameValuePair[] nameValuePairs = null;
            if (metaList != null) {
                nameValuePairs = new NameValuePair[metaList.size()];
                int index = 0;
                for (Iterator<Map.Entry<String,String>> iterator = metaList.entrySet().iterator(); iterator.hasNext();) {
                    Map.Entry<String,String> entry = iterator.next();
                    String name = entry.getKey();
                    String value = entry.getValue();
                    nameValuePairs[index++] = new NameValuePair(name,value);
                }
            }
            return storageClient.upload_file(GROUP_NAME, buff, prefix, nameValuePairs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Download files
     * @param fileId File ID (ID returned after successful upload)
     * @return
     */
    public byte[] downloadFile(String fileId) {
        try {
            byte[] content = storageClient.download_file(GROUP_NAME,fileId);
            return content;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Delete files
     * @param fileId File ID
     * @return Delete failed return - 1, otherwise return 0
     */
    public int deleteFile(String groupname,String fileId) {
        try {
            return storageClient.delete_file(groupname,fileId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * Getting file metadata
     * @param fileId File ID
     * @return
     */
    public Map<String,String> getFileMetadata(String groupname,String fileId) {
        try {
            NameValuePair[] metaList = storageClient.get_metadata(groupname,fileId);
            if (metaList != null) {
                HashMap<String,String> map = new HashMap<String, String>();
                for (NameValuePair metaItem : metaList) {
                    map.put(metaItem.getName(),metaItem.getValue());
                }
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

Explain

Core point is how to initialize the configuration file: ClientGlobal class commonly uses several initialization methods:

  • init(String conf_filename)
  • initByProperties(String propsFilePath)
  • initByProperties(Properties props)
  • initByTrackers(String trackerServers)

Core configuration parameters:

#Connecting tracker server timeout
connect_timeout = 2  
#socket connection timeout
network_timeout = 30
#File Content Coding 
charset = UTF-8 
#tracker server port
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key = FastDFS1234567890

#tracker server IP and ports (multiple writes)
tracker_server = 192.168.1.190:22122 

PS: Because the above example is just a demonstration, other configuration parameters ClientGlobal class have defaults, so the initialization parameter method used in the example can be directly passed into tracker_server's ip and port.

Error record:

1 java.net.SocketTimeoutException: connect timed out

Connection failure, as we have explored, can cause connection failure in the following two cases:
(1) Port not open
Because when using fastdfs-client-java, configuration only needs to configure the Tracker service address and port; this can easily lead to a misunderstanding that the external network port only needs to open the Tracker service port (default 22122). But in fact, Tracker service is only an intermediate service, it will get the available Storage service address and port, and the final file upload is directly uploaded to Storage service by the service we developed. Therefore, the server's external network port, must remember to open the Storage port (default 23000).

(2) Tracker address mismatch
Many people think that when configuring storage.conf, because both storage service and tracker service are on the intranet, intranet IP connections can be used. When the tracker address of Java service configuration belongs to the intranet gateway relationship, it needs to be configured as the extranet ip. But in fact, the tracker address of the Java service configuration, and the address of the storage. conf configuration, need to be accessible and consistent. One configures intranet IP and the other configures extranet ip, which causes a connection timed out error.

Topics: Java network socket