├── .gitignore ├── pom.xml └── src ├── main ├── java │ └── net │ │ └── mikesu │ │ └── fastdfs │ │ ├── FastdfsClient.java │ │ ├── FastdfsClientConfig.java │ │ ├── FastdfsClientFactory.java │ │ ├── FastdfsClientImpl.java │ │ ├── client │ │ ├── StorageClient.java │ │ ├── StorageClientFactory.java │ │ ├── StorageClientImpl.java │ │ ├── TrackerClient.java │ │ ├── TrackerClientFactory.java │ │ └── TrackerClientImpl.java │ │ ├── command │ │ ├── AbstractCmd.java │ │ ├── CloseCmd.java │ │ ├── Command.java │ │ ├── DeleteCmd.java │ │ ├── GetMetaDataCmd.java │ │ ├── GroupInfoCmd.java │ │ ├── QueryDownloadCmd.java │ │ ├── QueryUpdateCmd.java │ │ ├── QueryUploadCmd.java │ │ ├── SetMetaDataCmd.java │ │ ├── StorageInfoCmd.java │ │ └── UploadCmd.java │ │ ├── data │ │ ├── GroupInfo.java │ │ ├── Result.java │ │ ├── StorageInfo.java │ │ └── UploadStorage.java │ │ └── exception │ │ └── FastdfsIOException.java └── resources │ └── FastdfsClient.properties └── test ├── java └── net │ └── mikesu │ └── fastdfs │ ├── FastdfsClientConfigTest.java │ ├── FastdfsClientTest.java │ └── client │ └── TrackerClientTest.java └── resources ├── FastdfsClient.properties └── Koala.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.project 3 | /.settings 4 | /.classpath -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | net.mikesu 5 | FastdfsClient 6 | 0.0.1-SNAPSHOT 7 | FastDFS Java Client 8 | 9 | 10 | 11 | maven-compiler-plugin 12 | 3.1 13 | 14 | 1.7 15 | 1.7 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.apache.commons 23 | commons-pool2 24 | 2.2 25 | 26 | 27 | org.slf4j 28 | slf4j-api 29 | 1.7.5 30 | 31 | 32 | commons-configuration 33 | commons-configuration 34 | 1.10 35 | 36 | 37 | junit 38 | junit 39 | 4.11 40 | test 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/FastdfsClient.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs; 2 | 3 | import java.io.File; 4 | import java.util.Map; 5 | 6 | public interface FastdfsClient { 7 | 8 | public String upload(File file) throws Exception; 9 | public String upload(File file,String fileName) throws Exception; 10 | public String getUrl(String fileId) throws Exception; 11 | public Boolean setMeta(String fileId,Map meta) throws Exception; 12 | public Map getMeta(String fileId) throws Exception; 13 | public Boolean delete(String fileId) throws Exception; 14 | public void close(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/FastdfsClientConfig.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.apache.commons.configuration.Configuration; 7 | import org.apache.commons.configuration.ConfigurationException; 8 | import org.apache.commons.configuration.PropertiesConfiguration; 9 | import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; 10 | 11 | public class FastdfsClientConfig { 12 | 13 | public static final int DEFAULT_CONNECT_TIMEOUT = 5; // second 14 | public static final int DEFAULT_NETWORK_TIMEOUT = 30; // second 15 | 16 | private int connectTimeout = DEFAULT_CONNECT_TIMEOUT * 1000; 17 | private int networkTimeout = DEFAULT_NETWORK_TIMEOUT * 1000; 18 | private List trackerAddrs = new ArrayList(); 19 | // private int trackerClientPoolMaxIdlePerKey = 20 | 21 | public FastdfsClientConfig() { 22 | super(); 23 | // TODO Auto-generated constructor stub 24 | } 25 | 26 | public FastdfsClientConfig(String configFile) throws ConfigurationException { 27 | super(); 28 | // String conf = FastdfsClientConfig.class.getClassLoader().getResource(configFile).getPath(); 29 | Configuration config = new PropertiesConfiguration(configFile); 30 | this.connectTimeout = config.getInt("connect_timeout", DEFAULT_CONNECT_TIMEOUT)*1000; 31 | this.networkTimeout = config.getInt("network_timeout", DEFAULT_NETWORK_TIMEOUT)*1000; 32 | List trackerServers = config.getList("tracker_server"); 33 | for(Object trackerServer:trackerServers){ 34 | trackerAddrs.add((String)trackerServer); 35 | } 36 | } 37 | 38 | public int getConnectTimeout() { 39 | return connectTimeout; 40 | } 41 | 42 | public void setConnectTimeout(int connectTimeout) { 43 | this.connectTimeout = connectTimeout; 44 | } 45 | 46 | public int getNetworkTimeout() { 47 | return networkTimeout; 48 | } 49 | 50 | public void setNetworkTimeout(int networkTimeout) { 51 | this.networkTimeout = networkTimeout; 52 | } 53 | 54 | public List getTrackerAddrs() { 55 | return trackerAddrs; 56 | } 57 | 58 | public void setTrackerAddrs(List trackerAddrs) { 59 | this.trackerAddrs = trackerAddrs; 60 | } 61 | 62 | public GenericKeyedObjectPoolConfig getTrackerClientPoolConfig(){ 63 | GenericKeyedObjectPoolConfig poolConfig = new GenericKeyedObjectPoolConfig(); 64 | // poolConfig.setMaxIdlePerKey(maxIdlePerKey); 65 | // poolConfig.setMaxTotal(maxTotal); 66 | // poolConfig.setMaxTotalPerKey(maxTotalPerKey); 67 | // poolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 68 | // poolConfig.setma 69 | 70 | return poolConfig; 71 | } 72 | 73 | 74 | public GenericKeyedObjectPoolConfig getStorageClientPoolConfig(){ 75 | GenericKeyedObjectPoolConfig poolConfig = new GenericKeyedObjectPoolConfig(); 76 | return poolConfig; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/FastdfsClientFactory.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs; 2 | 3 | import java.util.List; 4 | 5 | import net.mikesu.fastdfs.client.StorageClient; 6 | import net.mikesu.fastdfs.client.StorageClientFactory; 7 | import net.mikesu.fastdfs.client.TrackerClient; 8 | import net.mikesu.fastdfs.client.TrackerClientFactory; 9 | 10 | import org.apache.commons.configuration.ConfigurationException; 11 | import org.apache.commons.pool2.impl.GenericKeyedObjectPool; 12 | import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; 13 | 14 | public class FastdfsClientFactory { 15 | 16 | private static volatile FastdfsClient fastdfsClient; 17 | 18 | public static FastdfsClient getFastdfsClient(List trackerAddrs){ 19 | FastdfsClientConfig config = new FastdfsClientConfig(); 20 | config.setTrackerAddrs(trackerAddrs); 21 | return getFastdfsClient(new FastdfsClientConfig()); 22 | } 23 | 24 | public static FastdfsClient getFastdfsClient(String configFileName) throws ConfigurationException{ 25 | FastdfsClientConfig config = new FastdfsClientConfig(configFileName); 26 | return getFastdfsClient(config); 27 | } 28 | 29 | public static FastdfsClient getFastdfsClient(FastdfsClientConfig config){ 30 | if (fastdfsClient == null) { 31 | synchronized (FastdfsClient.class) { 32 | if (fastdfsClient == null) { 33 | int connectTimeout = config.getConnectTimeout(); 34 | int networkTimeout = config.getNetworkTimeout(); 35 | TrackerClientFactory trackerClientFactory = new TrackerClientFactory(connectTimeout, networkTimeout); 36 | StorageClientFactory storageClientFactory = new StorageClientFactory(connectTimeout, networkTimeout); 37 | GenericKeyedObjectPoolConfig trackerClientPoolConfig = config.getTrackerClientPoolConfig(); 38 | GenericKeyedObjectPoolConfig storageClientPoolConfig = config.getStorageClientPoolConfig(); 39 | GenericKeyedObjectPool trackerClientPool = new GenericKeyedObjectPool<>(trackerClientFactory, trackerClientPoolConfig); 40 | GenericKeyedObjectPool storageClientPool = new GenericKeyedObjectPool<>(storageClientFactory, storageClientPoolConfig); 41 | List trackerAddrs = config.getTrackerAddrs(); 42 | fastdfsClient = new FastdfsClientImpl(trackerAddrs,trackerClientPool,storageClientPool); 43 | } 44 | } 45 | } 46 | return fastdfsClient; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/FastdfsClientImpl.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Random; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | import net.mikesu.fastdfs.client.StorageClient; 11 | import net.mikesu.fastdfs.client.StorageClientFactory; 12 | import net.mikesu.fastdfs.client.TrackerClient; 13 | import net.mikesu.fastdfs.client.TrackerClientFactory; 14 | import net.mikesu.fastdfs.data.GroupInfo; 15 | import net.mikesu.fastdfs.data.Result; 16 | import net.mikesu.fastdfs.data.StorageInfo; 17 | import net.mikesu.fastdfs.data.UploadStorage; 18 | 19 | import org.apache.commons.pool2.impl.GenericKeyedObjectPool; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | public class FastdfsClientImpl implements FastdfsClient{ 24 | 25 | private static Logger logger = LoggerFactory.getLogger(FastdfsClientImpl.class); 26 | private GenericKeyedObjectPool trackerClientPool; 27 | private GenericKeyedObjectPool storageClientPool; 28 | private List trackerAddrs = new ArrayList(); 29 | private Map storageIpMap = new ConcurrentHashMap(); 30 | 31 | public FastdfsClientImpl(List trackerAddrs) throws Exception { 32 | super(); 33 | this.trackerAddrs = trackerAddrs; 34 | trackerClientPool = new GenericKeyedObjectPool<>(new TrackerClientFactory()); 35 | storageClientPool = new GenericKeyedObjectPool<>(new StorageClientFactory()); 36 | updateStorageIpMap(); 37 | } 38 | 39 | public FastdfsClientImpl(List trackerAddrs, 40 | GenericKeyedObjectPool trackerClientPool, 41 | GenericKeyedObjectPool storageClientPool) { 42 | super(); 43 | this.trackerAddrs = trackerAddrs; 44 | this.trackerClientPool = trackerClientPool; 45 | this.storageClientPool = storageClientPool; 46 | } 47 | 48 | 49 | 50 | @Override 51 | public void close() { 52 | this.trackerClientPool.close(); 53 | this.storageClientPool.close(); 54 | } 55 | 56 | private void updateStorageIpMap() throws Exception{ 57 | String trackerAddr = getTrackerAddr(); 58 | TrackerClient trackerClient = null; 59 | try { 60 | trackerClient = trackerClientPool.borrowObject(trackerAddr); 61 | Result> result = trackerClient.getGroupInfos(); 62 | if(result.getCode()==0){ 63 | List groupInfos = result.getData(); 64 | for(GroupInfo groupInfo:groupInfos){ 65 | Result> result2= trackerClient.getStorageInfos(groupInfo.getGroupName()); 66 | if(result2.getCode()==0){ 67 | List storageInfos = result2.getData(); 68 | for(StorageInfo storageInfo:storageInfos){ 69 | String hostPort = storageInfo.getDomainName(); 70 | if(storageInfo.getStorageHttpPort()!=80){ 71 | hostPort = hostPort + ":" + storageInfo.getStorageHttpPort(); 72 | } 73 | storageIpMap.put(storageInfo.getIpAddr()+":"+storageInfo.getStoragePort(), hostPort); 74 | } 75 | } 76 | } 77 | }else{ 78 | throw new Exception("Get getGroupInfos Error"); 79 | } 80 | } catch (Exception e) { 81 | logger.error(e.getMessage()); 82 | throw e; 83 | } finally { 84 | if(trackerClient!=null){ 85 | trackerClientPool.returnObject(trackerAddr, trackerClient); 86 | } 87 | } 88 | } 89 | 90 | private String getDownloadHostPort(String storageAddr) throws Exception{ 91 | String downloadHostPort = storageIpMap.get(storageAddr); 92 | if(downloadHostPort==null){ 93 | updateStorageIpMap(); 94 | downloadHostPort = storageIpMap.get(storageAddr); 95 | } 96 | return downloadHostPort; 97 | } 98 | 99 | @Override 100 | public Boolean setMeta(String fileId, Map meta) 101 | throws Exception { 102 | String trackerAddr = getTrackerAddr(); 103 | TrackerClient trackerClient = null; 104 | StorageClient storageClient = null; 105 | Boolean result = null; 106 | String storageAddr=null; 107 | try{ 108 | FastDfsFile fastDfsFile = new FastDfsFile(fileId); 109 | trackerClient = trackerClientPool.borrowObject(trackerAddr); 110 | Result result2 = trackerClient.getUpdateStorageAddr(fastDfsFile.group, fastDfsFile.fileName); 111 | if(result2.getCode()==0){ 112 | storageAddr = result2.getData(); 113 | storageClient = storageClientPool.borrowObject(storageAddr); 114 | Result result3 = storageClient.setMeta(fastDfsFile.group, fastDfsFile.fileName,meta); 115 | if(result3.getCode()==0||result3.getCode()==0){ 116 | result = result3.getData(); 117 | } 118 | } 119 | } catch (Exception e) { 120 | logger.error(e.getMessage()); 121 | throw e; 122 | }finally{ 123 | if(storageClient!=null){ 124 | storageClientPool.returnObject(storageAddr, storageClient); 125 | } 126 | if(trackerClient!=null){ 127 | trackerClientPool.returnObject(trackerAddr, trackerClient); 128 | } 129 | } 130 | return result; 131 | } 132 | 133 | @Override 134 | public Map getMeta(String fileId) throws Exception { 135 | String trackerAddr = getTrackerAddr(); 136 | TrackerClient trackerClient = null; 137 | StorageClient storageClient = null; 138 | Map meta = null; 139 | String storageAddr=null; 140 | try{ 141 | FastDfsFile fastDfsFile = new FastDfsFile(fileId); 142 | trackerClient = trackerClientPool.borrowObject(trackerAddr); 143 | Result result2 = trackerClient.getUpdateStorageAddr(fastDfsFile.group, fastDfsFile.fileName); 144 | if(result2.getCode()==0){ 145 | storageAddr = result2.getData(); 146 | storageClient = storageClientPool.borrowObject(storageAddr); 147 | Result> result3 = storageClient.getMeta(fastDfsFile.group, fastDfsFile.fileName); 148 | if(result3.getCode()==0||result3.getCode()==0){ 149 | meta = result3.getData(); 150 | } 151 | } 152 | } catch (Exception e) { 153 | logger.error(e.getMessage()); 154 | throw e; 155 | }finally{ 156 | if(storageClient!=null){ 157 | storageClientPool.returnObject(storageAddr, storageClient); 158 | } 159 | if(trackerClient!=null){ 160 | trackerClientPool.returnObject(trackerAddr, trackerClient); 161 | } 162 | } 163 | return meta; 164 | } 165 | 166 | public String getUrl(String fileId) throws Exception{ 167 | String trackerAddr = getTrackerAddr(); 168 | TrackerClient trackerClient = null; 169 | String url = null; 170 | try { 171 | FastDfsFile fastDfsFile = new FastDfsFile(fileId); 172 | trackerClient = trackerClientPool.borrowObject(trackerAddr); 173 | Result result = trackerClient.getDownloadStorageAddr(fastDfsFile.group,fastDfsFile.fileName); 174 | if(result.getCode()==0){ 175 | String hostPort = getDownloadHostPort(result.getData()); 176 | url = "http://"+hostPort+"/"+fastDfsFile.fileName; 177 | } 178 | } catch (Exception e) { 179 | logger.error(e.getMessage()); 180 | throw e; 181 | } finally { 182 | if(trackerClient!=null){ 183 | trackerClientPool.returnObject(trackerAddr, trackerClient); 184 | } 185 | } 186 | return url; 187 | } 188 | 189 | public String upload(File file) throws Exception{ 190 | String fileName = file.getName(); 191 | return upload(file, fileName); 192 | } 193 | 194 | public String upload(File file,String fileName) throws Exception{ 195 | String trackerAddr = getTrackerAddr(); 196 | TrackerClient trackerClient = null; 197 | StorageClient storageClient = null; 198 | String storageAddr = null; 199 | String fileId = null; 200 | try { 201 | trackerClient = trackerClientPool.borrowObject(trackerAddr); 202 | Result result = trackerClient.getUploadStorage(); 203 | if(result.getCode()==0){ 204 | storageAddr = result.getData().getAddress(); 205 | storageClient = storageClientPool.borrowObject(storageAddr); 206 | Result result2 = storageClient.upload(file, fileName, result.getData().getPathIndex()); 207 | if(result2.getCode()==0){ 208 | fileId = result2.getData(); 209 | } 210 | } 211 | } catch (Exception e) { 212 | logger.error(e.getMessage()); 213 | throw e; 214 | } finally { 215 | if(storageClient!=null){ 216 | storageClientPool.returnObject(storageAddr, storageClient); 217 | } 218 | if(trackerClient!=null){ 219 | trackerClientPool.returnObject(trackerAddr, trackerClient); 220 | } 221 | } 222 | return fileId; 223 | } 224 | 225 | public Boolean delete(String fileId) throws Exception{ 226 | String trackerAddr = getTrackerAddr(); 227 | TrackerClient trackerClient = null; 228 | StorageClient storageClient = null; 229 | Boolean result=false; 230 | String storageAddr=null; 231 | try{ 232 | FastDfsFile fastDfsFile = new FastDfsFile(fileId); 233 | trackerClient = trackerClientPool.borrowObject(trackerAddr); 234 | Result result2 = trackerClient.getUpdateStorageAddr(fastDfsFile.group, fastDfsFile.fileName); 235 | if(result2.getCode()==0){ 236 | storageAddr = result2.getData(); 237 | storageClient = storageClientPool.borrowObject(storageAddr); 238 | Result result3 = storageClient.delete(fastDfsFile.group, fastDfsFile.fileName); 239 | if(result3.getCode()==0||result3.getCode()==0){ 240 | result = true; 241 | } 242 | } 243 | } catch (Exception e) { 244 | logger.error(e.getMessage()); 245 | throw e; 246 | }finally{ 247 | if(storageClient!=null){ 248 | storageClientPool.returnObject(storageAddr, storageClient); 249 | } 250 | if(trackerClient!=null){ 251 | trackerClientPool.returnObject(trackerAddr, trackerClient); 252 | } 253 | } 254 | return result; 255 | } 256 | 257 | public String getTrackerAddr(){ 258 | Random r = new Random(); 259 | int i = r.nextInt(trackerAddrs.size()); 260 | return trackerAddrs.get(i); 261 | } 262 | 263 | private class FastDfsFile{ 264 | private String group; 265 | private String fileName; 266 | 267 | public FastDfsFile(String fileId) { 268 | super(); 269 | int pos = fileId.indexOf("/"); 270 | group = fileId.substring(0, pos); 271 | fileName = fileId.substring(pos+1); 272 | } 273 | 274 | } 275 | 276 | 277 | } 278 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/client/StorageClient.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.client; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.Map; 6 | 7 | import net.mikesu.fastdfs.data.Result; 8 | 9 | public interface StorageClient { 10 | 11 | public Result upload(File file,String fileName,byte storePathIndex) throws IOException; 12 | public Result delete(String group,String fileName) throws IOException; 13 | public Result setMeta(String group,String fileName,Map meta) throws IOException; 14 | public Result> getMeta(String group,String fileName) throws IOException; 15 | public void close() throws IOException; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/client/StorageClientFactory.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.client; 2 | 3 | import java.io.IOException; 4 | 5 | import net.mikesu.fastdfs.FastdfsClientConfig; 6 | 7 | import org.apache.commons.pool2.KeyedPooledObjectFactory; 8 | import org.apache.commons.pool2.PooledObject; 9 | import org.apache.commons.pool2.impl.DefaultPooledObject; 10 | 11 | public class StorageClientFactory implements KeyedPooledObjectFactory { 12 | 13 | private Integer connectTimeout = FastdfsClientConfig.DEFAULT_CONNECT_TIMEOUT * 1000; 14 | private Integer networkTimeout = FastdfsClientConfig.DEFAULT_NETWORK_TIMEOUT * 1000; 15 | 16 | public StorageClientFactory() { 17 | super(); 18 | } 19 | 20 | public StorageClientFactory(Integer connectTimeout, Integer networkTimeout) { 21 | super(); 22 | this.connectTimeout = connectTimeout; 23 | this.networkTimeout = networkTimeout; 24 | } 25 | 26 | @Override 27 | public PooledObject makeObject(String key) { 28 | StorageClientImpl storageClient = new StorageClientImpl(key,connectTimeout,networkTimeout); 29 | PooledObject pooledStorageClient = new DefaultPooledObject(storageClient); 30 | return pooledStorageClient; 31 | } 32 | 33 | @Override 34 | public void destroyObject(String key, PooledObject pooledStorageClient) throws IOException { 35 | StorageClient storageClient = pooledStorageClient.getObject(); 36 | storageClient.close(); 37 | } 38 | 39 | @Override 40 | public boolean validateObject(String key, PooledObject p) { 41 | return true; 42 | } 43 | 44 | @Override 45 | public void activateObject(String key, PooledObject p) 46 | throws Exception { 47 | 48 | } 49 | 50 | @Override 51 | public void passivateObject(String key, PooledObject p) 52 | throws Exception { 53 | 54 | } 55 | 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/client/StorageClientImpl.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.client; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.InetSocketAddress; 6 | import java.net.Socket; 7 | import java.util.Map; 8 | 9 | import net.mikesu.fastdfs.FastdfsClientConfig; 10 | import net.mikesu.fastdfs.command.CloseCmd; 11 | import net.mikesu.fastdfs.command.Command; 12 | import net.mikesu.fastdfs.command.DeleteCmd; 13 | import net.mikesu.fastdfs.command.GetMetaDataCmd; 14 | import net.mikesu.fastdfs.command.SetMetaDataCmd; 15 | import net.mikesu.fastdfs.command.UploadCmd; 16 | import net.mikesu.fastdfs.data.Result; 17 | 18 | public class StorageClientImpl implements StorageClient{ 19 | 20 | private Socket socket; 21 | private String host; 22 | private Integer port; 23 | private Integer connectTimeout = FastdfsClientConfig.DEFAULT_CONNECT_TIMEOUT * 1000; 24 | private Integer networkTimeout = FastdfsClientConfig.DEFAULT_NETWORK_TIMEOUT * 1000; 25 | 26 | private Socket getSocket() throws IOException{ 27 | if(socket==null){ 28 | socket = new Socket(); 29 | socket.setSoTimeout(networkTimeout); 30 | socket.connect(new InetSocketAddress(host, port),connectTimeout); 31 | } 32 | return socket; 33 | } 34 | 35 | public StorageClientImpl(String address){ 36 | super(); 37 | String[] hostport = address.split(":"); 38 | this.host = hostport[0]; 39 | this.port = Integer.valueOf(hostport[1]); 40 | } 41 | 42 | public StorageClientImpl(String address,Integer connectTimeout, Integer networkTimeout){ 43 | this(address); 44 | this.connectTimeout = connectTimeout; 45 | this.networkTimeout = networkTimeout; 46 | } 47 | 48 | public void close() throws IOException{ 49 | Socket socket = getSocket(); 50 | Command command = new CloseCmd(); 51 | command.exec(socket); 52 | socket.close(); 53 | socket = null; 54 | } 55 | 56 | public Result upload(File file,String fileName,byte storePathIndex) throws IOException{ 57 | Socket socket = getSocket(); 58 | UploadCmd uploadCmd = new UploadCmd(file, fileName,storePathIndex); 59 | return uploadCmd.exec(socket); 60 | } 61 | 62 | public Result delete(String group,String fileName) throws IOException{ 63 | Socket socket = getSocket(); 64 | DeleteCmd deleteCmd = new DeleteCmd(group,fileName); 65 | return deleteCmd.exec(socket); 66 | } 67 | 68 | @Override 69 | public Result setMeta(String group, String fileName, 70 | Map meta) throws IOException { 71 | Socket socket = getSocket(); 72 | SetMetaDataCmd setMetaDataCmd = new SetMetaDataCmd(group, fileName, meta); 73 | return setMetaDataCmd.exec(socket); 74 | } 75 | 76 | @Override 77 | public Result> getMeta(String group, String fileName) 78 | throws IOException { 79 | Socket socket = getSocket(); 80 | GetMetaDataCmd getMetaDataCmd = new GetMetaDataCmd(group, fileName); 81 | return getMetaDataCmd.exec(socket); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/client/TrackerClient.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.client; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import net.mikesu.fastdfs.data.GroupInfo; 7 | import net.mikesu.fastdfs.data.Result; 8 | import net.mikesu.fastdfs.data.StorageInfo; 9 | import net.mikesu.fastdfs.data.UploadStorage; 10 | 11 | public interface TrackerClient { 12 | 13 | public Result getUploadStorage() throws IOException; 14 | public Result getUpdateStorageAddr(String group,String fileName) throws IOException; 15 | public Result getDownloadStorageAddr(String group,String fileName) throws IOException; 16 | public Result> getGroupInfos() throws IOException; 17 | public Result> getStorageInfos(String group) throws IOException; 18 | public void close() throws IOException; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/client/TrackerClientFactory.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.client; 2 | 3 | import java.io.IOException; 4 | 5 | import net.mikesu.fastdfs.FastdfsClientConfig; 6 | 7 | import org.apache.commons.pool2.KeyedPooledObjectFactory; 8 | import org.apache.commons.pool2.PooledObject; 9 | import org.apache.commons.pool2.impl.DefaultPooledObject; 10 | 11 | public class TrackerClientFactory implements KeyedPooledObjectFactory { 12 | 13 | private Integer connectTimeout = FastdfsClientConfig.DEFAULT_CONNECT_TIMEOUT * 1000; 14 | private Integer networkTimeout = FastdfsClientConfig.DEFAULT_NETWORK_TIMEOUT * 1000; 15 | 16 | public TrackerClientFactory() { 17 | super(); 18 | } 19 | 20 | public TrackerClientFactory(Integer connectTimeout, Integer networkTimeout) { 21 | super(); 22 | this.connectTimeout = connectTimeout; 23 | this.networkTimeout = networkTimeout; 24 | } 25 | 26 | @Override 27 | public PooledObject makeObject(String key){ 28 | TrackerClient trackerClient = new TrackerClientImpl(key,connectTimeout,networkTimeout); 29 | PooledObject pooledTrackerClient = new DefaultPooledObject(trackerClient); 30 | return pooledTrackerClient; 31 | } 32 | 33 | @Override 34 | public void destroyObject(String key, PooledObject pooledTrackerClient) throws IOException{ 35 | TrackerClient trackerClient = pooledTrackerClient.getObject(); 36 | trackerClient.close(); 37 | } 38 | 39 | @Override 40 | public boolean validateObject(String key, PooledObject p) { 41 | // TODO Auto-generated method stub 42 | return true; 43 | } 44 | 45 | @Override 46 | public void activateObject(String key, PooledObject p) 47 | throws Exception { 48 | // TODO Auto-generated method stub 49 | 50 | } 51 | 52 | @Override 53 | public void passivateObject(String key, PooledObject p) 54 | throws Exception { 55 | // TODO Auto-generated method stub 56 | 57 | } 58 | 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/client/TrackerClientImpl.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.client; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.net.Socket; 6 | import java.util.List; 7 | 8 | import net.mikesu.fastdfs.FastdfsClientConfig; 9 | import net.mikesu.fastdfs.command.CloseCmd; 10 | import net.mikesu.fastdfs.command.Command; 11 | import net.mikesu.fastdfs.command.GroupInfoCmd; 12 | import net.mikesu.fastdfs.command.QueryDownloadCmd; 13 | import net.mikesu.fastdfs.command.QueryUpdateCmd; 14 | import net.mikesu.fastdfs.command.QueryUploadCmd; 15 | import net.mikesu.fastdfs.command.StorageInfoCmd; 16 | import net.mikesu.fastdfs.data.GroupInfo; 17 | import net.mikesu.fastdfs.data.Result; 18 | import net.mikesu.fastdfs.data.StorageInfo; 19 | import net.mikesu.fastdfs.data.UploadStorage; 20 | 21 | public class TrackerClientImpl implements TrackerClient{ 22 | 23 | private Socket socket; 24 | private String host; 25 | private Integer port; 26 | private Integer connectTimeout = FastdfsClientConfig.DEFAULT_CONNECT_TIMEOUT * 1000; 27 | private Integer networkTimeout = FastdfsClientConfig.DEFAULT_NETWORK_TIMEOUT * 1000; 28 | 29 | public TrackerClientImpl(String address){ 30 | super(); 31 | String[] hostport = address.split(":"); 32 | this.host = hostport[0]; 33 | this.port = Integer.valueOf(hostport[1]); 34 | } 35 | 36 | public TrackerClientImpl(String address,Integer connectTimeout, Integer networkTimeout){ 37 | this(address); 38 | this.connectTimeout = connectTimeout; 39 | this.networkTimeout = networkTimeout; 40 | } 41 | 42 | private Socket getSocket() throws IOException{ 43 | if(socket==null){ 44 | socket = new Socket(); 45 | socket.setSoTimeout(networkTimeout); 46 | socket.connect(new InetSocketAddress(host, port),connectTimeout); 47 | } 48 | return socket; 49 | } 50 | 51 | 52 | public void close() throws IOException{ 53 | Socket socket = getSocket(); 54 | Command command = new CloseCmd(); 55 | command.exec(socket); 56 | socket.close(); 57 | socket = null; 58 | } 59 | 60 | 61 | public Result getUploadStorage() throws IOException{ 62 | Socket socket = getSocket(); 63 | Command command = new QueryUploadCmd(); 64 | return command.exec(socket); 65 | } 66 | 67 | public Result getUpdateStorageAddr(String group,String fileName) throws IOException{ 68 | Socket socket = getSocket(); 69 | Command cmd = new QueryUpdateCmd(group,fileName); 70 | return cmd.exec(socket); 71 | } 72 | 73 | public Result getDownloadStorageAddr(String group,String fileName) throws IOException{ 74 | Socket socket = getSocket(); 75 | Command cmd = new QueryDownloadCmd(group,fileName); 76 | return cmd.exec(socket); 77 | } 78 | 79 | public Result> getGroupInfos() throws IOException{ 80 | Socket socket = getSocket(); 81 | Command> cmd = new GroupInfoCmd(); 82 | return cmd.exec(socket); 83 | } 84 | 85 | public Result> getStorageInfos(String group) throws IOException{ 86 | Socket socket = getSocket(); 87 | Command> cmd = new StorageInfoCmd(group); 88 | return cmd.exec(socket); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/AbstractCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | import java.util.Arrays; 8 | 9 | public abstract class AbstractCmd implements Command { 10 | 11 | protected byte requestCmd; 12 | protected byte responseCmd; 13 | protected long responseSize; 14 | protected byte[] body1; 15 | protected long body2Len = 0l; 16 | 17 | protected void request(OutputStream socketOut)throws IOException { 18 | socketOut.write(getRequestHeaderAndBody1()); 19 | 20 | } 21 | 22 | protected void request(OutputStream socketOut,InputStream is)throws IOException { 23 | request(socketOut); 24 | int readBytes; 25 | byte[] buff = new byte[256 * 1024]; 26 | while ((readBytes = is.read(buff)) >= 0) { 27 | if (readBytes == 0) { 28 | continue; 29 | } 30 | socketOut.write(buff, 0, readBytes); 31 | } 32 | is.close(); 33 | } 34 | 35 | protected byte[] getRequestHeaderAndBody1() { 36 | if(body1==null){ 37 | body1 = new byte[0]; 38 | } 39 | byte[] header = new byte[FDFS_PROTO_PKG_LEN_SIZE + 2 + body1.length]; 40 | Arrays.fill(header, (byte) 0); 41 | byte[] hex_len = long2buff(body1.length+body2Len); 42 | System.arraycopy(hex_len, 0, header, 0, hex_len.length); 43 | System.arraycopy(body1, 0, header, FDFS_PROTO_PKG_LEN_SIZE + 2, body1.length); 44 | header[PROTO_HEADER_CMD_INDEX] = requestCmd; 45 | header[PROTO_HEADER_STATUS_INDEX] = (byte) 0; 46 | return header; 47 | } 48 | 49 | protected Response response(InputStream socketIn)throws IOException { 50 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 51 | int code = response(socketIn,os); 52 | return new Response(code, os.toByteArray()); 53 | 54 | } 55 | 56 | protected int response(InputStream socketIn,OutputStream os) throws IOException { 57 | byte[] header = new byte[FDFS_PROTO_PKG_LEN_SIZE + 2]; 58 | 59 | int bytes = socketIn.read(header); 60 | 61 | if (bytes != header.length) { 62 | throw new IOException("recv package size " + bytes + " != " + header.length); 63 | } 64 | 65 | if (header[PROTO_HEADER_CMD_INDEX] != responseCmd) { 66 | throw new IOException("recv cmd: " + header[PROTO_HEADER_CMD_INDEX] + " is not correct, expect cmd: " + responseCmd); 67 | } 68 | 69 | if (header[PROTO_HEADER_STATUS_INDEX] != SUCCESS_CODE) { 70 | return header[PROTO_HEADER_STATUS_INDEX]; 71 | } 72 | 73 | long respSize = buff2long(header, 0); 74 | if (respSize < 0) { 75 | throw new IOException("recv body length: " + respSize + " < 0!"); 76 | } 77 | 78 | if (responseSize >= 0 && respSize != responseSize) { 79 | throw new IOException("recv body length: " + respSize + " is not correct, expect length: " + responseSize); 80 | } 81 | 82 | 83 | byte[] buff = new byte[2 * 1024]; 84 | int totalBytes = 0; 85 | int remainBytes = (int) respSize; 86 | 87 | while (totalBytes < respSize) { 88 | int len = remainBytes; 89 | if(len>buff.length){ 90 | len = buff.length; 91 | } 92 | 93 | if ((bytes = socketIn.read(buff, 0, len)) < 0) { 94 | break; 95 | } 96 | os.write(buff, 0, bytes); 97 | totalBytes += bytes; 98 | remainBytes -= bytes; 99 | } 100 | 101 | if (totalBytes != respSize) { 102 | throw new IOException("recv package size " + totalBytes + " != "+ respSize); 103 | } 104 | os.close(); 105 | return SUCCESS_CODE; 106 | } 107 | 108 | public static byte[] long2buff(long n) { 109 | byte[] bs; 110 | 111 | bs = new byte[8]; 112 | bs[0] = (byte) ((n >> 56) & 0xFF); 113 | bs[1] = (byte) ((n >> 48) & 0xFF); 114 | bs[2] = (byte) ((n >> 40) & 0xFF); 115 | bs[3] = (byte) ((n >> 32) & 0xFF); 116 | bs[4] = (byte) ((n >> 24) & 0xFF); 117 | bs[5] = (byte) ((n >> 16) & 0xFF); 118 | bs[6] = (byte) ((n >> 8) & 0xFF); 119 | bs[7] = (byte) (n & 0xFF); 120 | 121 | return bs; 122 | } 123 | 124 | public static long buff2long(byte[] bs, int offset) { 125 | return (((long) (bs[offset] >= 0 ? bs[offset] : 256 + bs[offset])) << 56) 126 | | (((long) (bs[offset + 1] >= 0 ? bs[offset + 1] 127 | : 256 + bs[offset + 1])) << 48) 128 | | (((long) (bs[offset + 2] >= 0 ? bs[offset + 2] 129 | : 256 + bs[offset + 2])) << 40) 130 | | (((long) (bs[offset + 3] >= 0 ? bs[offset + 3] 131 | : 256 + bs[offset + 3])) << 32) 132 | | (((long) (bs[offset + 4] >= 0 ? bs[offset + 4] 133 | : 256 + bs[offset + 4])) << 24) 134 | | (((long) (bs[offset + 5] >= 0 ? bs[offset + 5] 135 | : 256 + bs[offset + 5])) << 16) 136 | | (((long) (bs[offset + 6] >= 0 ? bs[offset + 6] 137 | : 256 + bs[offset + 6])) << 8) 138 | | ((long) (bs[offset + 7] >= 0 ? bs[offset + 7] 139 | : 256 + bs[offset + 7])); 140 | } 141 | 142 | protected class Response { 143 | 144 | private int code; 145 | private byte[] data; 146 | 147 | public Response(int code) { 148 | super(); 149 | this.code = code; 150 | } 151 | public Response(int code, byte[] data) { 152 | super(); 153 | this.code = code; 154 | this.data = data; 155 | } 156 | public boolean isSuccess(){ 157 | return code == SUCCESS_CODE; 158 | } 159 | public int getCode() { 160 | return code; 161 | } 162 | public void setCode(int code) { 163 | this.code = code; 164 | } 165 | public byte[] getData() { 166 | return data; 167 | } 168 | public void setData(byte[] data) { 169 | this.data = data; 170 | } 171 | 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/CloseCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | 6 | import net.mikesu.fastdfs.data.Result; 7 | 8 | public class CloseCmd extends AbstractCmd { 9 | 10 | public CloseCmd() { 11 | super(); 12 | this.requestCmd = FDFS_PROTO_CMD_QUIT; 13 | } 14 | 15 | @Override 16 | public Result exec(Socket socket) throws IOException { 17 | request(socket.getOutputStream()); 18 | return new Result(SUCCESS_CODE,true); 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/Command.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.nio.charset.Charset; 6 | 7 | import net.mikesu.fastdfs.data.Result; 8 | 9 | public interface Command { 10 | 11 | public Result exec(Socket socket) throws IOException; 12 | 13 | 14 | public static final byte FDFS_PROTO_CMD_QUIT = 82; 15 | public static final byte TRACKER_PROTO_CMD_SERVER_LIST_GROUP = 91; 16 | public static final byte TRACKER_PROTO_CMD_SERVER_LIST_STORAGE = 92; 17 | public static final byte TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE = 93; 18 | public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE = 101; 19 | public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE = 102; 20 | public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE = 103; 21 | public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE = 104; 22 | public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL = 105; 23 | public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL = 106; 24 | public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL = 107; 25 | public static final byte TRACKER_PROTO_CMD_RESP = 100; 26 | public static final byte FDFS_PROTO_CMD_ACTIVE_TEST = 111; 27 | public static final byte STORAGE_PROTO_CMD_UPLOAD_FILE = 11; 28 | public static final byte STORAGE_PROTO_CMD_DELETE_FILE = 12; 29 | public static final byte STORAGE_PROTO_CMD_SET_METADATA = 13; 30 | public static final byte STORAGE_PROTO_CMD_DOWNLOAD_FILE = 14; 31 | public static final byte STORAGE_PROTO_CMD_GET_METADATA = 15; 32 | public static final byte STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE = 21; 33 | public static final byte STORAGE_PROTO_CMD_QUERY_FILE_INFO = 22; 34 | public static final byte STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE = 23; // create appender file 35 | public static final byte STORAGE_PROTO_CMD_APPEND_FILE = 24; // append file 36 | public static final byte STORAGE_PROTO_CMD_MODIFY_FILE = 34; // modify appender file 37 | public static final byte STORAGE_PROTO_CMD_TRUNCATE_FILE = 36; // truncate appender file 38 | public static final byte STORAGE_PROTO_CMD_RESP = TRACKER_PROTO_CMD_RESP; 39 | 40 | public static final byte FDFS_STORAGE_STATUS_INIT = 0; 41 | public static final byte FDFS_STORAGE_STATUS_WAIT_SYNC = 1; 42 | public static final byte FDFS_STORAGE_STATUS_SYNCING = 2; 43 | public static final byte FDFS_STORAGE_STATUS_IP_CHANGED = 3; 44 | public static final byte FDFS_STORAGE_STATUS_DELETED = 4; 45 | public static final byte FDFS_STORAGE_STATUS_OFFLINE = 5; 46 | public static final byte FDFS_STORAGE_STATUS_ONLINE = 6; 47 | public static final byte FDFS_STORAGE_STATUS_ACTIVE = 7; 48 | public static final byte FDFS_STORAGE_STATUS_NONE = 99; 49 | 50 | /** 51 | * for overwrite all old metadata 52 | */ 53 | public static final byte STORAGE_SET_METADATA_FLAG_OVERWRITE = 'O'; 54 | 55 | /** 56 | * for replace, insert when the meta item not exist, otherwise update it 57 | */ 58 | public static final byte STORAGE_SET_METADATA_FLAG_MERGE = 'M'; 59 | 60 | public static final int FDFS_PROTO_PKG_LEN_SIZE = 8; 61 | public static final int FDFS_PROTO_CMD_SIZE = 1; 62 | public static final int FDFS_GROUP_NAME_MAX_LEN = 16; 63 | public static final int FDFS_IPADDR_SIZE = 16; 64 | public static final int FDFS_DOMAIN_NAME_MAX_SIZE = 128; 65 | public static final int FDFS_VERSION_SIZE = 6; 66 | public static final int FDFS_STORAGE_ID_MAX_SIZE = 16; 67 | 68 | public static final String FDFS_RECORD_SEPERATOR = "\u0001"; 69 | public static final String FDFS_FIELD_SEPERATOR = "\u0002"; 70 | 71 | public static final int TRACKER_QUERY_STORAGE_FETCH_BODY_LEN = FDFS_GROUP_NAME_MAX_LEN + FDFS_IPADDR_SIZE - 1 + FDFS_PROTO_PKG_LEN_SIZE; 72 | public static final int TRACKER_QUERY_STORAGE_STORE_BODY_LEN = FDFS_GROUP_NAME_MAX_LEN + FDFS_IPADDR_SIZE + FDFS_PROTO_PKG_LEN_SIZE; 73 | 74 | public static final int PROTO_HEADER_CMD_INDEX = FDFS_PROTO_PKG_LEN_SIZE; 75 | public static final int PROTO_HEADER_STATUS_INDEX = FDFS_PROTO_PKG_LEN_SIZE + 1; 76 | 77 | public static final byte FDFS_FILE_EXT_NAME_MAX_LEN = 6; 78 | public static final byte FDFS_FILE_PREFIX_MAX_LEN = 16; 79 | public static final byte FDFS_FILE_PATH_LEN = 10; 80 | public static final byte FDFS_FILENAME_BASE64_LENGTH = 27; 81 | public static final byte FDFS_TRUNK_FILE_INFO_LEN = 16; 82 | 83 | public static final byte ERR_NO_ENOENT = 2; 84 | public static final byte ERR_NO_EIO = 5; 85 | public static final byte ERR_NO_EBUSY = 16; 86 | public static final byte ERR_NO_EINVAL = 22; 87 | public static final byte ERR_NO_ENOSPC = 28; 88 | public static final byte ECONNREFUSED = 61; 89 | public static final byte ERR_NO_EALREADY = 114; 90 | 91 | public static final long INFINITE_FILE_SIZE = 256 * 1024L * 1024 * 1024 * 1024 * 1024L; 92 | public static final long APPENDER_FILE_SIZE = INFINITE_FILE_SIZE; 93 | public static final long TRUNK_FILE_MARK_SIZE = 512 * 1024L * 1024 * 1024 * 1024 * 1024L; 94 | public static final long NORMAL_LOGIC_FILENAME_LENGTH = FDFS_FILE_PATH_LEN + FDFS_FILENAME_BASE64_LENGTH + FDFS_FILE_EXT_NAME_MAX_LEN + 1; 95 | public static final long TRUNK_LOGIC_FILENAME_LENGTH = NORMAL_LOGIC_FILENAME_LENGTH + FDFS_TRUNK_FILE_INFO_LEN; 96 | 97 | public static final int SUCCESS_CODE = 0; 98 | public Charset charset = Charset.forName("UTF-8"); 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/DeleteCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.util.Arrays; 6 | 7 | import net.mikesu.fastdfs.data.Result; 8 | 9 | public class DeleteCmd extends AbstractCmd { 10 | 11 | @Override 12 | public Result exec(Socket socket) throws IOException { 13 | request(socket.getOutputStream()); 14 | Response response = response(socket.getInputStream()); 15 | if(response.isSuccess()){ 16 | return new Result(response.getCode(),true); 17 | }else{ 18 | return new Result(response.getCode(),"Delete Error"); 19 | } 20 | } 21 | 22 | public DeleteCmd(String group,String fileName) { 23 | super(); 24 | byte[] groupByte = group.getBytes(charset); 25 | int group_len = groupByte.length; 26 | if (group_len > FDFS_GROUP_NAME_MAX_LEN) { 27 | group_len = FDFS_GROUP_NAME_MAX_LEN; 28 | } 29 | byte[] fileNameByte = fileName.getBytes(charset); 30 | body1 = new byte[FDFS_GROUP_NAME_MAX_LEN + fileNameByte.length]; 31 | Arrays.fill(body1, (byte) 0); 32 | System.arraycopy(groupByte, 0, body1, 0, group_len); 33 | System.arraycopy(fileNameByte, 0, body1, FDFS_GROUP_NAME_MAX_LEN, fileNameByte.length); 34 | this.requestCmd = STORAGE_PROTO_CMD_DELETE_FILE; 35 | this.responseCmd = STORAGE_PROTO_CMD_RESP; 36 | this.responseSize = 0; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/GetMetaDataCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.util.Arrays; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import net.mikesu.fastdfs.data.Result; 10 | 11 | public class GetMetaDataCmd extends AbstractCmd> { 12 | 13 | @Override 14 | public Result> exec(Socket socket) throws IOException { 15 | request(socket.getOutputStream()); 16 | Response response = response(socket.getInputStream()); 17 | if(response.isSuccess()){ 18 | String metaStr = new String(response.getData(),charset); 19 | Map metaData = new HashMap(); 20 | String[] rows = metaStr.split(FDFS_RECORD_SEPERATOR); 21 | for(String row:rows){ 22 | String[] cols = row.split(FDFS_FIELD_SEPERATOR); 23 | metaData.put(cols[0], cols[1]); 24 | } 25 | return new Result>(response.getCode(),metaData); 26 | }else{ 27 | return new Result>(response.getCode(),"GetMetaData Error"); 28 | } 29 | } 30 | 31 | public GetMetaDataCmd(String group, String fileName) { 32 | super(); 33 | byte[] groupByte = group.getBytes(charset); 34 | int group_len = groupByte.length; 35 | if (group_len > FDFS_GROUP_NAME_MAX_LEN) { 36 | group_len = FDFS_GROUP_NAME_MAX_LEN; 37 | } 38 | byte[] fileNameByte = fileName.getBytes(charset); 39 | body1 = new byte[FDFS_GROUP_NAME_MAX_LEN + fileNameByte.length]; 40 | Arrays.fill(body1, (byte) 0); 41 | System.arraycopy(groupByte, 0, body1, 0, group_len); 42 | System.arraycopy(fileNameByte, 0, body1, FDFS_GROUP_NAME_MAX_LEN, fileNameByte.length); 43 | this.requestCmd = STORAGE_PROTO_CMD_GET_METADATA; 44 | this.responseCmd = STORAGE_PROTO_CMD_RESP; 45 | this.responseSize = -1; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/GroupInfoCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import net.mikesu.fastdfs.data.GroupInfo; 9 | import net.mikesu.fastdfs.data.Result; 10 | 11 | public class GroupInfoCmd extends AbstractCmd> { 12 | 13 | @Override 14 | public Result> exec(Socket socket) throws IOException { 15 | request(socket.getOutputStream()); 16 | Response response = response(socket.getInputStream()); 17 | if(response.isSuccess()){ 18 | byte[] data = response.getData(); 19 | int dataLength = data.length; 20 | if(dataLength%GroupInfo.BYTE_SIZE!=0){ 21 | throw new IOException("recv body length: " + data.length + " is not correct"); 22 | } 23 | List groupInfos = new ArrayList(); 24 | int offset = 0; 25 | while(offset>(response.getCode(),groupInfos); 31 | }else{ 32 | return new Result>(response.getCode(),"Error"); 33 | } 34 | } 35 | 36 | public GroupInfoCmd() { 37 | super(); 38 | this.requestCmd = TRACKER_PROTO_CMD_SERVER_LIST_GROUP; 39 | this.responseCmd = TRACKER_PROTO_CMD_RESP; 40 | this.responseSize = -1; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/QueryDownloadCmd.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikesu/FastdfsClient/ae53f7786c0029c2539510ec3c4a1d89aba60a1e/src/main/java/net/mikesu/fastdfs/command/QueryDownloadCmd.java -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/QueryUpdateCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.util.Arrays; 6 | 7 | import net.mikesu.fastdfs.data.Result; 8 | 9 | public class QueryUpdateCmd extends AbstractCmd { 10 | 11 | @Override 12 | public Result exec(Socket socket) throws IOException { 13 | request(socket.getOutputStream()); 14 | Response response = response(socket.getInputStream()); 15 | if(response.isSuccess()){ 16 | byte[] data = response.getData(); 17 | String ip = new String(data,FDFS_GROUP_NAME_MAX_LEN,FDFS_IPADDR_SIZE - 1).trim(); 18 | int port = (int) buff2long(data, FDFS_GROUP_NAME_MAX_LEN + FDFS_IPADDR_SIZE - 1); 19 | Result result = new Result(response.getCode()); 20 | result.setData(ip + ":" + String.valueOf(port)); 21 | return result; 22 | } 23 | else{ 24 | Result result = new Result(response.getCode()); 25 | result.setMessage("Error"); 26 | return result; 27 | } 28 | } 29 | 30 | public QueryUpdateCmd(String group,String fileName) { 31 | super(); 32 | byte[] groupByte = group.getBytes(charset); 33 | int group_len = groupByte.length; 34 | if (group_len > FDFS_GROUP_NAME_MAX_LEN) { 35 | group_len = FDFS_GROUP_NAME_MAX_LEN; 36 | } 37 | byte[] fileNameByte = fileName.getBytes(charset); 38 | body1 = new byte[FDFS_GROUP_NAME_MAX_LEN + fileNameByte.length]; 39 | Arrays.fill(body1, (byte) 0); 40 | System.arraycopy(groupByte, 0, body1, 0, group_len); 41 | System.arraycopy(fileNameByte, 0, body1, FDFS_GROUP_NAME_MAX_LEN, fileNameByte.length); 42 | this.requestCmd = TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE; 43 | this.responseCmd = TRACKER_PROTO_CMD_RESP; 44 | this.responseSize = TRACKER_QUERY_STORAGE_FETCH_BODY_LEN; 45 | } 46 | 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/QueryUploadCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.io.UnsupportedEncodingException; 5 | import java.net.Socket; 6 | import java.util.Arrays; 7 | 8 | import net.mikesu.fastdfs.data.Result; 9 | import net.mikesu.fastdfs.data.UploadStorage; 10 | 11 | 12 | public class QueryUploadCmd extends AbstractCmd { 13 | 14 | 15 | @Override 16 | public Result exec(Socket socket) throws IOException { 17 | request(socket.getOutputStream()); 18 | Response response = response(socket.getInputStream()); 19 | if(response.isSuccess()){ 20 | byte[] data = response.getData(); 21 | String ip_addr = new String(data,FDFS_GROUP_NAME_MAX_LEN,FDFS_IPADDR_SIZE - 1).trim(); 22 | int port = (int) buff2long(data,FDFS_GROUP_NAME_MAX_LEN + FDFS_IPADDR_SIZE - 1); 23 | byte storePath = data[TRACKER_QUERY_STORAGE_STORE_BODY_LEN - 1]; 24 | UploadStorage uploadStorage = new UploadStorage(ip_addr+":"+String.valueOf(port), storePath); 25 | return new Result(response.getCode(),uploadStorage); 26 | }else{ 27 | return new Result(response.getCode(),"Error"); 28 | } 29 | } 30 | 31 | 32 | public QueryUploadCmd() { 33 | super(); 34 | this.requestCmd = TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE; 35 | this.responseCmd = TRACKER_PROTO_CMD_RESP; 36 | this.responseSize = TRACKER_QUERY_STORAGE_STORE_BODY_LEN; 37 | } 38 | 39 | public QueryUploadCmd(String group) throws UnsupportedEncodingException { 40 | super(); 41 | int group_len; 42 | byte[] bs = group.getBytes("UTF-8"); 43 | body1 = new byte[FDFS_GROUP_NAME_MAX_LEN]; 44 | if (bs.length <= FDFS_GROUP_NAME_MAX_LEN) { 45 | group_len = bs.length; 46 | } else { 47 | group_len = FDFS_GROUP_NAME_MAX_LEN; 48 | } 49 | Arrays.fill(body1, (byte) 0); 50 | System.arraycopy(bs, 0, body1, 0, group_len); 51 | this.requestCmd = TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE; 52 | this.responseCmd = TRACKER_PROTO_CMD_RESP; 53 | this.responseSize = TRACKER_QUERY_STORAGE_STORE_BODY_LEN; 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/SetMetaDataCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.util.Arrays; 6 | import java.util.Map; 7 | 8 | import net.mikesu.fastdfs.data.Result; 9 | 10 | public class SetMetaDataCmd extends AbstractCmd { 11 | 12 | @Override 13 | public Result exec(Socket socket) throws IOException { 14 | request(socket.getOutputStream()); 15 | Response response = response(socket.getInputStream()); 16 | if(response.isSuccess()){ 17 | return new Result(response.getCode(),true); 18 | }else{ 19 | return new Result(response.getCode(),"SetMetaData Error"); 20 | } 21 | } 22 | 23 | public SetMetaDataCmd(String group,String fileName,Map metaData) { 24 | super(); 25 | byte[] groupByte = group.getBytes(charset); 26 | int group_len = groupByte.length; 27 | if (group_len > FDFS_GROUP_NAME_MAX_LEN) { 28 | group_len = FDFS_GROUP_NAME_MAX_LEN; 29 | } 30 | byte[] fileNameByte = fileName.getBytes(charset); 31 | byte[] fileNameSizeByte = long2buff(fileNameByte.length); 32 | byte[] metaDataByte = metaDataToStr(metaData).getBytes(charset); 33 | byte[] metaDataSizeByte = long2buff(metaDataByte.length); 34 | 35 | body1 = new byte[2 * FDFS_PROTO_PKG_LEN_SIZE + 1 + FDFS_GROUP_NAME_MAX_LEN + fileNameByte.length + metaDataByte.length]; 36 | 37 | Arrays.fill(body1, (byte) 0); 38 | int pos = 0; 39 | System.arraycopy(fileNameSizeByte, 0, body1, pos, fileNameSizeByte.length); 40 | pos += FDFS_PROTO_PKG_LEN_SIZE; 41 | System.arraycopy(metaDataSizeByte, 0, body1, pos, metaDataSizeByte.length); 42 | pos += FDFS_PROTO_PKG_LEN_SIZE; 43 | body1[pos] = STORAGE_SET_METADATA_FLAG_OVERWRITE; 44 | pos += 1; 45 | System.arraycopy(groupByte, 0, body1, pos, group_len); 46 | pos += FDFS_GROUP_NAME_MAX_LEN; 47 | System.arraycopy(fileNameByte, 0, body1, pos, fileNameByte.length); 48 | pos += fileNameByte.length; 49 | System.arraycopy(metaDataByte, 0, body1, pos, metaDataByte.length); 50 | 51 | this.requestCmd = STORAGE_PROTO_CMD_SET_METADATA; 52 | this.responseCmd = STORAGE_PROTO_CMD_RESP; 53 | this.responseSize = 0; 54 | } 55 | 56 | private String metaDataToStr(Map metaData){ 57 | StringBuffer sb = new StringBuffer(); 58 | for(String key:metaData.keySet()){ 59 | sb.append(FDFS_RECORD_SEPERATOR); 60 | sb.append(key); 61 | sb.append(FDFS_FIELD_SEPERATOR); 62 | sb.append(metaData.get(key)); 63 | } 64 | 65 | return sb.toString().substring(FDFS_RECORD_SEPERATOR.length()); 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/StorageInfoCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.IOException; 4 | import java.io.UnsupportedEncodingException; 5 | import java.net.Socket; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | import net.mikesu.fastdfs.data.Result; 11 | import net.mikesu.fastdfs.data.StorageInfo; 12 | 13 | public class StorageInfoCmd extends AbstractCmd> { 14 | 15 | @Override 16 | public Result> exec(Socket socket) throws IOException { 17 | request(socket.getOutputStream()); 18 | Response response = response(socket.getInputStream()); 19 | if(response.isSuccess()){ 20 | byte[] data = response.getData(); 21 | int dataLength = data.length; 22 | if(dataLength%StorageInfo.BYTE_SIZE!=0){ 23 | throw new IOException("recv body length: " + data.length + " is not correct"); 24 | } 25 | List storageInfos = new ArrayList(); 26 | int offset = 0; 27 | while(offset(response.getCode(), storageInfos); 33 | }else{ 34 | return new Result<>(response.getCode(), "Error"); 35 | } 36 | } 37 | 38 | public StorageInfoCmd(String group) throws UnsupportedEncodingException { 39 | super(); 40 | int group_len; 41 | byte[] bs = group.getBytes("UTF-8"); 42 | body1 = new byte[FDFS_GROUP_NAME_MAX_LEN]; 43 | if (bs.length <= FDFS_GROUP_NAME_MAX_LEN) { 44 | group_len = bs.length; 45 | } else { 46 | group_len = FDFS_GROUP_NAME_MAX_LEN; 47 | } 48 | Arrays.fill(body1, (byte) 0); 49 | System.arraycopy(bs, 0, body1, 0, group_len); 50 | this.requestCmd = TRACKER_PROTO_CMD_SERVER_LIST_STORAGE; 51 | this.responseCmd = TRACKER_PROTO_CMD_RESP; 52 | this.responseSize = -1; 53 | } 54 | 55 | public StorageInfoCmd(String group,String ip) throws UnsupportedEncodingException { 56 | super(); 57 | int group_len; 58 | byte[] groupByte = group.getBytes("UTF-8"); 59 | byte[] ipByte = ip.getBytes("UTF-8"); 60 | body1 = new byte[FDFS_GROUP_NAME_MAX_LEN + ipByte.length]; 61 | if (groupByte.length <= FDFS_GROUP_NAME_MAX_LEN) { 62 | group_len = groupByte.length; 63 | } else { 64 | group_len = FDFS_GROUP_NAME_MAX_LEN; 65 | } 66 | Arrays.fill(body1, (byte) 0); 67 | System.arraycopy(groupByte, 0, body1, 0, group_len); 68 | System.arraycopy(ipByte, 0, body1, FDFS_GROUP_NAME_MAX_LEN, ipByte.length); 69 | this.requestCmd = TRACKER_PROTO_CMD_SERVER_LIST_STORAGE; 70 | this.responseCmd = TRACKER_PROTO_CMD_RESP; 71 | this.responseSize = -1; 72 | } 73 | 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/command/UploadCmd.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.command; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.net.Socket; 8 | import java.util.Arrays; 9 | 10 | import net.mikesu.fastdfs.data.Result; 11 | 12 | public class UploadCmd extends AbstractCmd { 13 | 14 | private File file; 15 | 16 | @Override 17 | public Result exec(Socket socket) throws IOException { 18 | InputStream is = new FileInputStream(file); 19 | request(socket.getOutputStream(), is); 20 | Response response = response(socket.getInputStream()); 21 | if(response.isSuccess()){ 22 | byte[] data = response.getData(); 23 | String group = new String(data, 0, FDFS_GROUP_NAME_MAX_LEN).trim(); 24 | String remoteFileName = new String(data,FDFS_GROUP_NAME_MAX_LEN, data.length - FDFS_GROUP_NAME_MAX_LEN); 25 | Result result = new Result<>(response.getCode()); 26 | result.setData(group + "/" + remoteFileName); 27 | return result; 28 | }else{ 29 | Result result = new Result<>(response.getCode()); 30 | result.setMessage("Error"); 31 | return result; 32 | } 33 | } 34 | 35 | public UploadCmd(File file,String fileName,byte storePathIndex){ 36 | super(); 37 | this.file = file; 38 | this.requestCmd = STORAGE_PROTO_CMD_UPLOAD_FILE; 39 | this.body2Len = file.length(); 40 | this.responseCmd = STORAGE_PROTO_CMD_RESP; 41 | this.responseSize = -1; 42 | this.body1 = new byte[15]; 43 | Arrays.fill(body1, (byte) 0); 44 | this.body1[0] = storePathIndex; 45 | byte[] fileSizeByte = long2buff(file.length()); 46 | byte[] fileExtNameByte = getFileExtNameByte(fileName); 47 | int fileExtNameByteLen = fileExtNameByte.length; 48 | if(fileExtNameByteLen>FDFS_FILE_EXT_NAME_MAX_LEN){ 49 | fileExtNameByteLen = FDFS_FILE_EXT_NAME_MAX_LEN; 50 | } 51 | System.arraycopy(fileSizeByte, 0, body1, 1, fileSizeByte.length); 52 | System.arraycopy(fileExtNameByte, 0, body1, fileSizeByte.length + 1, fileExtNameByteLen); 53 | } 54 | 55 | private byte[] getFileExtNameByte(String fileName) { 56 | String fileExtName = null; 57 | int nPos = fileName.lastIndexOf('.'); 58 | if (nPos > 0 && fileName.length() - nPos <= FDFS_FILE_EXT_NAME_MAX_LEN + 1) { 59 | fileExtName = fileName.substring(nPos + 1); 60 | } 61 | if (fileExtName != null && fileExtName.length() > 0) { 62 | return fileExtName.getBytes(charset); 63 | }else{ 64 | return new byte[0]; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/data/GroupInfo.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.data; 2 | 3 | import net.mikesu.fastdfs.command.AbstractCmd; 4 | 5 | public class GroupInfo { 6 | 7 | private String groupName; // name of this group 8 | private long totalMB; // total disk storage in MB 9 | private long freeMB; // free disk space in MB 10 | private long trunkFreeMB; // trunk free space in MB 11 | private int storageCount; // storage server count 12 | private int storagePort; // storage server port 13 | private int storageHttpPort; // storage server HTTP port 14 | private int activeCount; // active storage server count 15 | private int currentWriteServer; // current storage server index to upload file 16 | private int storePathCount; // store base path count of each storage server 17 | private int subdirCountPerPath; // sub dir count per store path 18 | private int currentTrunkFileId; // current trunk file id 19 | public final static int BYTE_SIZE = 105; 20 | 21 | 22 | public GroupInfo(byte[] data,int offset) { 23 | super(); 24 | groupName = new String(data, offset, AbstractCmd.FDFS_GROUP_NAME_MAX_LEN+1).trim(); 25 | offset += AbstractCmd.FDFS_GROUP_NAME_MAX_LEN+1; 26 | totalMB = AbstractCmd.buff2long(data, offset); 27 | offset += 8; 28 | freeMB = AbstractCmd.buff2long(data, offset); 29 | offset += 8; 30 | trunkFreeMB = AbstractCmd.buff2long(data, offset); 31 | offset += 8; 32 | storageCount = (int) AbstractCmd.buff2long(data, offset); 33 | offset += 8; 34 | storagePort = (int) AbstractCmd.buff2long(data, offset); 35 | offset += 8; 36 | storageHttpPort = (int) AbstractCmd.buff2long(data, offset); 37 | offset += 8; 38 | activeCount = (int) AbstractCmd.buff2long(data, offset); 39 | offset += 8; 40 | currentWriteServer = (int) AbstractCmd.buff2long(data, offset); 41 | offset += 8; 42 | storePathCount = (int) AbstractCmd.buff2long(data, offset); 43 | offset += 8; 44 | subdirCountPerPath = (int) AbstractCmd.buff2long(data, offset); 45 | offset += 8; 46 | currentTrunkFileId = (int) AbstractCmd.buff2long(data, offset); 47 | } 48 | 49 | 50 | public String getGroupName() { 51 | return groupName; 52 | } 53 | public void setGroupName(String groupName) { 54 | this.groupName = groupName; 55 | } 56 | public long getTotalMB() { 57 | return totalMB; 58 | } 59 | public void setTotalMB(long totalMB) { 60 | this.totalMB = totalMB; 61 | } 62 | public long getFreeMB() { 63 | return freeMB; 64 | } 65 | public void setFreeMB(long freeMB) { 66 | this.freeMB = freeMB; 67 | } 68 | public long getTrunkFreeMB() { 69 | return trunkFreeMB; 70 | } 71 | public void setTrunkFreeMB(long trunkFreeMB) { 72 | this.trunkFreeMB = trunkFreeMB; 73 | } 74 | public int getStorageCount() { 75 | return storageCount; 76 | } 77 | public void setStorageCount(int storageCount) { 78 | this.storageCount = storageCount; 79 | } 80 | public int getStoragePort() { 81 | return storagePort; 82 | } 83 | public void setStoragePort(int storagePort) { 84 | this.storagePort = storagePort; 85 | } 86 | public int getStorageHttpPort() { 87 | return storageHttpPort; 88 | } 89 | public void setStorageHttpPort(int storageHttpPort) { 90 | this.storageHttpPort = storageHttpPort; 91 | } 92 | public int getActiveCount() { 93 | return activeCount; 94 | } 95 | public void setActiveCount(int activeCount) { 96 | this.activeCount = activeCount; 97 | } 98 | public int getCurrentWriteServer() { 99 | return currentWriteServer; 100 | } 101 | public void setCurrentWriteServer(int currentWriteServer) { 102 | this.currentWriteServer = currentWriteServer; 103 | } 104 | public int getStorePathCount() { 105 | return storePathCount; 106 | } 107 | public void setStorePathCount(int storePathCount) { 108 | this.storePathCount = storePathCount; 109 | } 110 | public int getSubdirCountPerPath() { 111 | return subdirCountPerPath; 112 | } 113 | public void setSubdirCountPerPath(int subdirCountPerPath) { 114 | this.subdirCountPerPath = subdirCountPerPath; 115 | } 116 | public int getCurrentTrunkFileId() { 117 | return currentTrunkFileId; 118 | } 119 | public void setCurrentTrunkFileId(int currentTrunkFileId) { 120 | this.currentTrunkFileId = currentTrunkFileId; 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/data/Result.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.data; 2 | 3 | public class Result { 4 | 5 | private int code; 6 | private String message; 7 | private T data; 8 | 9 | public Result(int code) { 10 | super(); 11 | this.code = code; 12 | } 13 | 14 | public Result(int code, String message) { 15 | super(); 16 | this.code = code; 17 | this.message = message; 18 | } 19 | 20 | public Result(int code, T data) { 21 | super(); 22 | this.code = code; 23 | this.data = data; 24 | } 25 | 26 | public String getMessage() { 27 | return message; 28 | } 29 | 30 | public void setMessage(String message) { 31 | this.message = message; 32 | } 33 | 34 | public int getCode() { 35 | return code; 36 | } 37 | public void setCode(int code) { 38 | this.code = code; 39 | } 40 | public T getData() { 41 | return data; 42 | } 43 | public void setData(T data) { 44 | this.data = data; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/data/StorageInfo.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.data; 2 | 3 | import java.util.Date; 4 | 5 | import net.mikesu.fastdfs.command.AbstractCmd; 6 | 7 | public class StorageInfo { 8 | 9 | protected byte status; 10 | protected String id; 11 | protected String ipAddr; 12 | protected String domainName; // http domain name 13 | protected String srcIpAddr; 14 | protected String version; 15 | protected Date joinTime; // storage join timestamp (create timestamp) 16 | protected Date upTime; // storage service started timestamp 17 | protected long totalMB; // total disk storage in MB 18 | protected long freeMB; // free disk storage in MB 19 | 20 | protected int uploadPriority; // upload priority 21 | protected int storePathCount; // store base path count of each storage 22 | protected int subdirCountPerPath; 23 | protected int currentWritePath; // current write path index 24 | protected int storagePort; 25 | protected int storageHttpPort; // storage http server port 26 | 27 | protected long totalUploadCount; 28 | protected long successUploadCount; 29 | protected long totalAppendCount; 30 | protected long successAppendCount; 31 | protected long totalModifyCount; 32 | protected long successModifyCount; 33 | protected long totalTruncateCount; 34 | protected long successTruncateCount; 35 | protected long totalSetMetaCount; 36 | protected long successSetMetaCount; 37 | protected long totalDeleteCount; 38 | protected long successDeleteCount; 39 | protected long totalDownloadCount; 40 | protected long successDownloadCount; 41 | protected long totalGetMetaCount; 42 | protected long successGetMetaCount; 43 | protected long totalCreateLinkCount; 44 | protected long successCreateLinkCount; 45 | protected long totalDeleteLinkCount; 46 | protected long successDeleteLinkCount; 47 | protected long totalUploadBytes; 48 | protected long successUploadBytes; 49 | protected long totalAppendBytes; 50 | protected long successAppendBytes; 51 | protected long totalModifyBytes; 52 | protected long successModifyBytes; 53 | protected long totalDownloadloadBytes; 54 | protected long successDownloadloadBytes; 55 | protected long totalSyncInBytes; 56 | protected long successSyncInBytes; 57 | protected long totalSyncOutBytes; 58 | protected long successSyncOutBytes; 59 | protected long totalFileOpenCount; 60 | protected long successFileOpenCount; 61 | protected long totalFileReadCount; 62 | protected long successFileReadCount; 63 | protected long totalFileWriteCount; 64 | protected long successFileWriteCount; 65 | 66 | protected Date lastSourceUpdate; 67 | protected Date lastSyncUpdate; 68 | protected Date lastSyncedTimestamp; 69 | protected Date lastHeartBeatTime; 70 | protected boolean ifTrunkServer; 71 | public final static int BYTE_SIZE = 600; 72 | 73 | 74 | public StorageInfo(byte[] data,int offset) { 75 | status = data[offset]; 76 | offset += 1; 77 | id = new String(data, offset, AbstractCmd.FDFS_STORAGE_ID_MAX_SIZE).trim(); 78 | offset += AbstractCmd.FDFS_STORAGE_ID_MAX_SIZE; 79 | ipAddr = new String(data, offset, AbstractCmd.FDFS_IPADDR_SIZE).trim(); 80 | offset += AbstractCmd.FDFS_IPADDR_SIZE; 81 | domainName = new String(data, offset, AbstractCmd.FDFS_DOMAIN_NAME_MAX_SIZE).trim(); 82 | offset += AbstractCmd.FDFS_DOMAIN_NAME_MAX_SIZE; 83 | srcIpAddr = new String(data, offset, AbstractCmd.FDFS_IPADDR_SIZE).trim(); 84 | offset += AbstractCmd.FDFS_IPADDR_SIZE; 85 | version = new String(data, offset, AbstractCmd.FDFS_VERSION_SIZE).trim(); 86 | offset += AbstractCmd.FDFS_VERSION_SIZE; 87 | joinTime = new Date(AbstractCmd.buff2long(data, offset) * 1000); 88 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 89 | upTime = new Date(AbstractCmd.buff2long(data, offset) * 1000); 90 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 91 | totalMB = AbstractCmd.buff2long(data, offset); 92 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 93 | freeMB = AbstractCmd.buff2long(data, offset); 94 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 95 | uploadPriority = (int) AbstractCmd.buff2long(data, offset); 96 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 97 | storePathCount = (int) AbstractCmd.buff2long(data, offset); 98 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 99 | subdirCountPerPath = (int) AbstractCmd.buff2long(data, offset); 100 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 101 | currentWritePath = (int) AbstractCmd.buff2long(data, offset); 102 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 103 | storagePort = (int) AbstractCmd.buff2long(data, offset); 104 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 105 | storageHttpPort = (int) AbstractCmd.buff2long(data, offset); 106 | 107 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 108 | totalUploadCount = AbstractCmd.buff2long(data, offset); 109 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 110 | successUploadCount = AbstractCmd.buff2long(data, offset); 111 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 112 | totalAppendCount = AbstractCmd.buff2long(data, offset); 113 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 114 | successAppendCount = AbstractCmd.buff2long(data, offset); 115 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 116 | totalModifyCount = AbstractCmd.buff2long(data, offset); 117 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 118 | successModifyCount = AbstractCmd.buff2long(data, offset); 119 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 120 | totalTruncateCount = AbstractCmd.buff2long(data, offset); 121 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 122 | successTruncateCount = AbstractCmd.buff2long(data, offset); 123 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 124 | totalSetMetaCount = AbstractCmd.buff2long(data, offset); 125 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 126 | successSetMetaCount = AbstractCmd.buff2long(data, offset); 127 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 128 | totalDeleteCount = AbstractCmd.buff2long(data, offset); 129 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 130 | successDeleteCount = AbstractCmd.buff2long(data, offset); 131 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 132 | totalDownloadCount = AbstractCmd.buff2long(data, offset); 133 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 134 | successDownloadCount = AbstractCmd.buff2long(data, offset); 135 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 136 | totalGetMetaCount = AbstractCmd.buff2long(data, offset); 137 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 138 | successGetMetaCount = AbstractCmd.buff2long(data, offset); 139 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 140 | totalCreateLinkCount = AbstractCmd.buff2long(data, offset); 141 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 142 | successCreateLinkCount = AbstractCmd.buff2long(data, offset); 143 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 144 | totalDeleteLinkCount = AbstractCmd.buff2long(data, offset); 145 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 146 | successDeleteLinkCount = AbstractCmd.buff2long(data, offset); 147 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 148 | totalUploadBytes = AbstractCmd.buff2long(data, offset); 149 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 150 | successUploadBytes = AbstractCmd.buff2long(data, offset); 151 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 152 | totalAppendBytes = AbstractCmd.buff2long(data, offset); 153 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 154 | successAppendBytes = AbstractCmd.buff2long(data, offset); 155 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 156 | totalModifyBytes = AbstractCmd.buff2long(data, offset); 157 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 158 | successModifyBytes = AbstractCmd.buff2long(data, offset); 159 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 160 | totalDownloadloadBytes = AbstractCmd.buff2long(data, offset); 161 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 162 | successDownloadloadBytes = AbstractCmd.buff2long(data, offset); 163 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 164 | totalSyncInBytes = AbstractCmd.buff2long(data, offset); 165 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 166 | successSyncInBytes = AbstractCmd.buff2long(data, offset); 167 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 168 | totalSyncOutBytes = AbstractCmd.buff2long(data, offset); 169 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 170 | successSyncOutBytes = AbstractCmd.buff2long(data, offset); 171 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 172 | totalFileOpenCount = AbstractCmd.buff2long(data, offset); 173 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 174 | successFileOpenCount = AbstractCmd.buff2long(data, offset); 175 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 176 | totalFileReadCount = AbstractCmd.buff2long(data, offset); 177 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 178 | successFileReadCount = AbstractCmd.buff2long(data, offset); 179 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 180 | totalFileWriteCount = AbstractCmd.buff2long(data, offset); 181 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 182 | successFileWriteCount = AbstractCmd.buff2long(data, offset); 183 | 184 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 185 | lastSourceUpdate = new Date(AbstractCmd.buff2long(data, offset) * 1000); 186 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 187 | lastSyncUpdate = new Date(AbstractCmd.buff2long(data, offset) * 1000); 188 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 189 | lastSyncedTimestamp = new Date(AbstractCmd.buff2long(data, offset) * 1000); 190 | offset += AbstractCmd.FDFS_PROTO_PKG_LEN_SIZE; 191 | lastHeartBeatTime = new Date(AbstractCmd.buff2long(data, offset) * 1000); 192 | 193 | ifTrunkServer = (data[offset] != 0); 194 | } 195 | 196 | 197 | public byte getStatus() { 198 | return status; 199 | } 200 | public void setStatus(byte status) { 201 | this.status = status; 202 | } 203 | public String getId() { 204 | return id; 205 | } 206 | public void setId(String id) { 207 | this.id = id; 208 | } 209 | public String getIpAddr() { 210 | return ipAddr; 211 | } 212 | public void setIpAddr(String ipAddr) { 213 | this.ipAddr = ipAddr; 214 | } 215 | public String getSrcIpAddr() { 216 | return srcIpAddr; 217 | } 218 | public void setSrcIpAddr(String srcIpAddr) { 219 | this.srcIpAddr = srcIpAddr; 220 | } 221 | public String getDomainName() { 222 | return domainName; 223 | } 224 | public void setDomainName(String domainName) { 225 | this.domainName = domainName; 226 | } 227 | public String getVersion() { 228 | return version; 229 | } 230 | public void setVersion(String version) { 231 | this.version = version; 232 | } 233 | public long getTotalMB() { 234 | return totalMB; 235 | } 236 | public void setTotalMB(long totalMB) { 237 | this.totalMB = totalMB; 238 | } 239 | public long getFreeMB() { 240 | return freeMB; 241 | } 242 | public void setFreeMB(long freeMB) { 243 | this.freeMB = freeMB; 244 | } 245 | public int getUploadPriority() { 246 | return uploadPriority; 247 | } 248 | public void setUploadPriority(int uploadPriority) { 249 | this.uploadPriority = uploadPriority; 250 | } 251 | public Date getJoinTime() { 252 | return joinTime; 253 | } 254 | public void setJoinTime(Date joinTime) { 255 | this.joinTime = joinTime; 256 | } 257 | public Date getUpTime() { 258 | return upTime; 259 | } 260 | public void setUpTime(Date upTime) { 261 | this.upTime = upTime; 262 | } 263 | public int getStorePathCount() { 264 | return storePathCount; 265 | } 266 | public void setStorePathCount(int storePathCount) { 267 | this.storePathCount = storePathCount; 268 | } 269 | public int getSubdirCountPerPath() { 270 | return subdirCountPerPath; 271 | } 272 | public void setSubdirCountPerPath(int subdirCountPerPath) { 273 | this.subdirCountPerPath = subdirCountPerPath; 274 | } 275 | public int getStoragePort() { 276 | return storagePort; 277 | } 278 | public void setStoragePort(int storagePort) { 279 | this.storagePort = storagePort; 280 | } 281 | public int getStorageHttpPort() { 282 | return storageHttpPort; 283 | } 284 | public void setStorageHttpPort(int storageHttpPort) { 285 | this.storageHttpPort = storageHttpPort; 286 | } 287 | public int getCurrentWritePath() { 288 | return currentWritePath; 289 | } 290 | public void setCurrentWritePath(int currentWritePath) { 291 | this.currentWritePath = currentWritePath; 292 | } 293 | public long getTotalUploadCount() { 294 | return totalUploadCount; 295 | } 296 | public void setTotalUploadCount(long totalUploadCount) { 297 | this.totalUploadCount = totalUploadCount; 298 | } 299 | public long getSuccessUploadCount() { 300 | return successUploadCount; 301 | } 302 | public void setSuccessUploadCount(long successUploadCount) { 303 | this.successUploadCount = successUploadCount; 304 | } 305 | public long getTotalAppendCount() { 306 | return totalAppendCount; 307 | } 308 | public void setTotalAppendCount(long totalAppendCount) { 309 | this.totalAppendCount = totalAppendCount; 310 | } 311 | public long getSuccessAppendCount() { 312 | return successAppendCount; 313 | } 314 | public void setSuccessAppendCount(long successAppendCount) { 315 | this.successAppendCount = successAppendCount; 316 | } 317 | public long getTotalModifyCount() { 318 | return totalModifyCount; 319 | } 320 | public void setTotalModifyCount(long totalModifyCount) { 321 | this.totalModifyCount = totalModifyCount; 322 | } 323 | public long getSuccessModifyCount() { 324 | return successModifyCount; 325 | } 326 | public void setSuccessModifyCount(long successModifyCount) { 327 | this.successModifyCount = successModifyCount; 328 | } 329 | public long getTotalTruncateCount() { 330 | return totalTruncateCount; 331 | } 332 | public void setTotalTruncateCount(long totalTruncateCount) { 333 | this.totalTruncateCount = totalTruncateCount; 334 | } 335 | public long getSuccessTruncateCount() { 336 | return successTruncateCount; 337 | } 338 | public void setSuccessTruncateCount(long successTruncateCount) { 339 | this.successTruncateCount = successTruncateCount; 340 | } 341 | public long getTotalSetMetaCount() { 342 | return totalSetMetaCount; 343 | } 344 | public void setTotalSetMetaCount(long totalSetMetaCount) { 345 | this.totalSetMetaCount = totalSetMetaCount; 346 | } 347 | public long getSuccessSetMetaCount() { 348 | return successSetMetaCount; 349 | } 350 | public void setSuccessSetMetaCount(long successSetMetaCount) { 351 | this.successSetMetaCount = successSetMetaCount; 352 | } 353 | public long getTotalDeleteCount() { 354 | return totalDeleteCount; 355 | } 356 | public void setTotalDeleteCount(long totalDeleteCount) { 357 | this.totalDeleteCount = totalDeleteCount; 358 | } 359 | public long getSuccessDeleteCount() { 360 | return successDeleteCount; 361 | } 362 | public void setSuccessDeleteCount(long successDeleteCount) { 363 | this.successDeleteCount = successDeleteCount; 364 | } 365 | public long getTotalDownloadCount() { 366 | return totalDownloadCount; 367 | } 368 | public void setTotalDownloadCount(long totalDownloadCount) { 369 | this.totalDownloadCount = totalDownloadCount; 370 | } 371 | public long getSuccessDownloadCount() { 372 | return successDownloadCount; 373 | } 374 | public void setSuccessDownloadCount(long successDownloadCount) { 375 | this.successDownloadCount = successDownloadCount; 376 | } 377 | public long getTotalGetMetaCount() { 378 | return totalGetMetaCount; 379 | } 380 | public void setTotalGetMetaCount(long totalGetMetaCount) { 381 | this.totalGetMetaCount = totalGetMetaCount; 382 | } 383 | public long getSuccessGetMetaCount() { 384 | return successGetMetaCount; 385 | } 386 | public void setSuccessGetMetaCount(long successGetMetaCount) { 387 | this.successGetMetaCount = successGetMetaCount; 388 | } 389 | public long getTotalCreateLinkCount() { 390 | return totalCreateLinkCount; 391 | } 392 | public void setTotalCreateLinkCount(long totalCreateLinkCount) { 393 | this.totalCreateLinkCount = totalCreateLinkCount; 394 | } 395 | public long getSuccessCreateLinkCount() { 396 | return successCreateLinkCount; 397 | } 398 | public void setSuccessCreateLinkCount(long successCreateLinkCount) { 399 | this.successCreateLinkCount = successCreateLinkCount; 400 | } 401 | public long getTotalDeleteLinkCount() { 402 | return totalDeleteLinkCount; 403 | } 404 | public void setTotalDeleteLinkCount(long totalDeleteLinkCount) { 405 | this.totalDeleteLinkCount = totalDeleteLinkCount; 406 | } 407 | public long getSuccessDeleteLinkCount() { 408 | return successDeleteLinkCount; 409 | } 410 | public void setSuccessDeleteLinkCount(long successDeleteLinkCount) { 411 | this.successDeleteLinkCount = successDeleteLinkCount; 412 | } 413 | public long getTotalUploadBytes() { 414 | return totalUploadBytes; 415 | } 416 | public void setTotalUploadBytes(long totalUploadBytes) { 417 | this.totalUploadBytes = totalUploadBytes; 418 | } 419 | public long getSuccessUploadBytes() { 420 | return successUploadBytes; 421 | } 422 | public void setSuccessUploadBytes(long successUploadBytes) { 423 | this.successUploadBytes = successUploadBytes; 424 | } 425 | public long getTotalAppendBytes() { 426 | return totalAppendBytes; 427 | } 428 | public void setTotalAppendBytes(long totalAppendBytes) { 429 | this.totalAppendBytes = totalAppendBytes; 430 | } 431 | public long getSuccessAppendBytes() { 432 | return successAppendBytes; 433 | } 434 | public void setSuccessAppendBytes(long successAppendBytes) { 435 | this.successAppendBytes = successAppendBytes; 436 | } 437 | public long getTotalModifyBytes() { 438 | return totalModifyBytes; 439 | } 440 | public void setTotalModifyBytes(long totalModifyBytes) { 441 | this.totalModifyBytes = totalModifyBytes; 442 | } 443 | public long getSuccessModifyBytes() { 444 | return successModifyBytes; 445 | } 446 | public void setSuccessModifyBytes(long successModifyBytes) { 447 | this.successModifyBytes = successModifyBytes; 448 | } 449 | public long getTotalDownloadloadBytes() { 450 | return totalDownloadloadBytes; 451 | } 452 | public void setTotalDownloadloadBytes(long totalDownloadloadBytes) { 453 | this.totalDownloadloadBytes = totalDownloadloadBytes; 454 | } 455 | public long getSuccessDownloadloadBytes() { 456 | return successDownloadloadBytes; 457 | } 458 | public void setSuccessDownloadloadBytes(long successDownloadloadBytes) { 459 | this.successDownloadloadBytes = successDownloadloadBytes; 460 | } 461 | public long getTotalSyncInBytes() { 462 | return totalSyncInBytes; 463 | } 464 | public void setTotalSyncInBytes(long totalSyncInBytes) { 465 | this.totalSyncInBytes = totalSyncInBytes; 466 | } 467 | public long getSuccessSyncInBytes() { 468 | return successSyncInBytes; 469 | } 470 | public void setSuccessSyncInBytes(long successSyncInBytes) { 471 | this.successSyncInBytes = successSyncInBytes; 472 | } 473 | public long getTotalSyncOutBytes() { 474 | return totalSyncOutBytes; 475 | } 476 | public void setTotalSyncOutBytes(long totalSyncOutBytes) { 477 | this.totalSyncOutBytes = totalSyncOutBytes; 478 | } 479 | public long getSuccessSyncOutBytes() { 480 | return successSyncOutBytes; 481 | } 482 | public void setSuccessSyncOutBytes(long successSyncOutBytes) { 483 | this.successSyncOutBytes = successSyncOutBytes; 484 | } 485 | public long getTotalFileOpenCount() { 486 | return totalFileOpenCount; 487 | } 488 | public void setTotalFileOpenCount(long totalFileOpenCount) { 489 | this.totalFileOpenCount = totalFileOpenCount; 490 | } 491 | public long getSuccessFileOpenCount() { 492 | return successFileOpenCount; 493 | } 494 | public void setSuccessFileOpenCount(long successFileOpenCount) { 495 | this.successFileOpenCount = successFileOpenCount; 496 | } 497 | public long getTotalFileReadCount() { 498 | return totalFileReadCount; 499 | } 500 | public void setTotalFileReadCount(long totalFileReadCount) { 501 | this.totalFileReadCount = totalFileReadCount; 502 | } 503 | public long getSuccessFileReadCount() { 504 | return successFileReadCount; 505 | } 506 | public void setSuccessFileReadCount(long successFileReadCount) { 507 | this.successFileReadCount = successFileReadCount; 508 | } 509 | public long getTotalFileWriteCount() { 510 | return totalFileWriteCount; 511 | } 512 | public void setTotalFileWriteCount(long totalFileWriteCount) { 513 | this.totalFileWriteCount = totalFileWriteCount; 514 | } 515 | public long getSuccessFileWriteCount() { 516 | return successFileWriteCount; 517 | } 518 | public void setSuccessFileWriteCount(long successFileWriteCount) { 519 | this.successFileWriteCount = successFileWriteCount; 520 | } 521 | public Date getLastSourceUpdate() { 522 | return lastSourceUpdate; 523 | } 524 | public void setLastSourceUpdate(Date lastSourceUpdate) { 525 | this.lastSourceUpdate = lastSourceUpdate; 526 | } 527 | public Date getLastSyncUpdate() { 528 | return lastSyncUpdate; 529 | } 530 | public void setLastSyncUpdate(Date lastSyncUpdate) { 531 | this.lastSyncUpdate = lastSyncUpdate; 532 | } 533 | public Date getLastSyncedTimestamp() { 534 | return lastSyncedTimestamp; 535 | } 536 | public void setLastSyncedTimestamp(Date lastSyncedTimestamp) { 537 | this.lastSyncedTimestamp = lastSyncedTimestamp; 538 | } 539 | public Date getLastHeartBeatTime() { 540 | return lastHeartBeatTime; 541 | } 542 | public void setLastHeartBeatTime(Date lastHeartBeatTime) { 543 | this.lastHeartBeatTime = lastHeartBeatTime; 544 | } 545 | public boolean isIfTrunkServer() { 546 | return ifTrunkServer; 547 | } 548 | public void setIfTrunkServer(boolean ifTrunkServer) { 549 | this.ifTrunkServer = ifTrunkServer; 550 | } 551 | 552 | 553 | } 554 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/data/UploadStorage.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.data; 2 | 3 | public class UploadStorage { 4 | 5 | private String address; 6 | private byte pathIndex; 7 | public UploadStorage(String address, byte pathIndex) { 8 | super(); 9 | this.address = address; 10 | this.pathIndex = pathIndex; 11 | } 12 | public String getAddress() { 13 | return address; 14 | } 15 | public void setAddress(String address) { 16 | this.address = address; 17 | } 18 | public byte getPathIndex() { 19 | return pathIndex; 20 | } 21 | public void setPathIndex(byte pathIndex) { 22 | this.pathIndex = pathIndex; 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/net/mikesu/fastdfs/exception/FastdfsIOException.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.exception; 2 | 3 | public class FastdfsIOException extends Exception { 4 | 5 | private static final long serialVersionUID = 4234899139606659965L; 6 | 7 | public FastdfsIOException() { 8 | super(); 9 | } 10 | 11 | public FastdfsIOException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | 15 | public FastdfsIOException(String message) { 16 | super(message); 17 | } 18 | 19 | public FastdfsIOException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/FastdfsClient.properties: -------------------------------------------------------------------------------- 1 | connect_timeout=5 2 | network_timeout=30 3 | tracker_server=10.125.176.138:22122 -------------------------------------------------------------------------------- /src/test/java/net/mikesu/fastdfs/FastdfsClientConfigTest.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.apache.commons.configuration.ConfigurationException; 6 | import org.junit.Test; 7 | 8 | public class FastdfsClientConfigTest { 9 | 10 | @Test 11 | public void testFastdfsClientConfigString() throws ConfigurationException { 12 | FastdfsClientConfig fastdfsClientConfig = new FastdfsClientConfig("FastdfsClient.properties"); 13 | assertEquals(5*1000, fastdfsClientConfig.getConnectTimeout()); 14 | assertEquals(30*1000,fastdfsClientConfig.getNetworkTimeout()); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/net/mikesu/fastdfs/FastdfsClientTest.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.File; 6 | import java.net.URL; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import org.junit.Test; 11 | 12 | public class FastdfsClientTest { 13 | 14 | 15 | @Test 16 | public void testFastdfsClient() throws Exception { 17 | FastdfsClient fastdfsClient = FastdfsClientFactory.getFastdfsClient("FastdfsClient.properties"); 18 | URL fileUrl = this.getClass().getResource("/Koala.jpg"); 19 | File file = new File(fileUrl.getPath()); 20 | String fileId = fastdfsClient.upload(file); 21 | System.out.println("fileId:"+fileId); 22 | assertNotNull(fileId); 23 | String url = fastdfsClient.getUrl(fileId); 24 | assertNotNull(url); 25 | System.out.println("url:"+url); 26 | Map meta = new HashMap(); 27 | meta.put("fileName", file.getName()); 28 | boolean result = fastdfsClient.setMeta(fileId, meta); 29 | assertTrue(result); 30 | Map meta2 = fastdfsClient.getMeta(fileId); 31 | assertNotNull(meta2); 32 | System.out.println(meta2.get("fileName")); 33 | result = fastdfsClient.delete(fileId); 34 | assertTrue(result); 35 | fastdfsClient.close(); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/net/mikesu/fastdfs/client/TrackerClientTest.java: -------------------------------------------------------------------------------- 1 | package net.mikesu.fastdfs.client; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | import java.net.UnknownHostException; 7 | import java.util.List; 8 | 9 | import net.mikesu.fastdfs.data.GroupInfo; 10 | import net.mikesu.fastdfs.data.Result; 11 | import net.mikesu.fastdfs.data.UploadStorage; 12 | 13 | import org.junit.Test; 14 | 15 | public class TrackerClientTest { 16 | 17 | @Test 18 | public void testGetUploadStorageAddr() throws NumberFormatException, UnknownHostException, IOException { 19 | TrackerClient trackerClient = new TrackerClientImpl("10.125.176.138:22122"); 20 | Result result = trackerClient.getUploadStorage(); 21 | assertEquals(0, result.getCode()); 22 | assertEquals("10.125.176.138:23000",result.getData().getAddress()); 23 | trackerClient.close(); 24 | } 25 | 26 | @Test 27 | public void testGetDownloadStorageAddr() throws IOException { 28 | TrackerClient trackerClient = new TrackerClientImpl("10.125.176.138:22122"); 29 | Result result = trackerClient.getDownloadStorageAddr("group1","M00/00/00/Cn2wilM00puAa0xSAANVQ4eIxAM143.jpg"); 30 | assertEquals(0, result.getCode()); 31 | assertEquals("10.125.176.138:23000",result.getData()); 32 | trackerClient.close(); 33 | } 34 | 35 | @Test 36 | public void testGetUpdateStorageAddr() throws IOException { 37 | TrackerClient trackerClient = new TrackerClientImpl("10.125.176.138:22122"); 38 | Result result = trackerClient.getUpdateStorageAddr("group1","M00/00/00/Cn2wilM00puAa0xSAANVQ4eIxAM143.jpg"); 39 | assertEquals(0, result.getCode()); 40 | assertEquals("10.125.176.138:23000",result.getData()); 41 | trackerClient.close(); 42 | } 43 | 44 | @Test 45 | public void testGetGroupInfos() throws NumberFormatException, UnknownHostException, IOException{ 46 | TrackerClient trackerClient = new TrackerClientImpl("10.125.176.138:22122"); 47 | Result> groupInfos = trackerClient.getGroupInfos(); 48 | assertNotNull(groupInfos); 49 | trackerClient.close(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/resources/FastdfsClient.properties: -------------------------------------------------------------------------------- 1 | connect_timeout=5 2 | network_timeout=30 3 | tracker_server=10.125.176.138:22122 -------------------------------------------------------------------------------- /src/test/resources/Koala.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikesu/FastdfsClient/ae53f7786c0029c2539510ec3c4a1d89aba60a1e/src/test/resources/Koala.jpg --------------------------------------------------------------------------------