File Upload and Download Process with FastDFS
Upload Flow
- The client contacts the Tracker server.
- Tracker responds with the IP adress and port of a Storage server.
- The client communicates directly with the Storage server to send the file content and metadata.
- Storage returns the file's storage identifier, including group name and file name.
FastDFS Java Client Integration
Dependency Setup
<dependencies>
<dependency>
<groupId>cn.bestwu</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
Configuration File
File name: fdfs_client.conf
Udpate with your tracker server IP:
connect_timeout = 10
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 8080
tracker_server = 192.168.93.10:22122
Utility Class Implementation
Place in package com.msb.utils.FastDFSClient
package com.msb.utils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.lang3.StringUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
public class FastDFSClient {
private static final String CONF_FILENAME = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";
private static StorageClient storageClient = null;
static {
try {
ClientGlobal.init(CONF_FILENAME);
TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
storageClient = new StorageClient(trackerServer, storageServer);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String[] uploadFile(InputStream inputStream, String fileName) {
try {
NameValuePair[] meta_list = new NameValuePair[2];
meta_list[0] = new NameValuePair("file name", fileName);
meta_list[1] = new NameValuePair("file length", inputStream.available()+"");
byte[] file_buff = null;
if (inputStream != null) {
int len = inputStream.available();
file_buff = new byte[len];
inputStream.read(file_buff);
}
String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
return fileids;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
public static String[] uploadFile(File file, String fileName) {
FileInputStream fis = null;
try {
NameValuePair[] meta_list = null;
fis = new FileInputStream(file);
byte[] file_buff = null;
if (fis != null) {
int len = fis.available();
file_buff = new byte[len];
fis.read(file_buff);
}
String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
return fileids;
} catch (Exception ex) {
return null;
} finally {
if (fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static int deleteFile(String groupName, String remoteFileName) {
try {
int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
return result;
} catch (Exception ex) {
return 0;
}
}
public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) {
String[] fileids = null;
try {
fileids = uploadFile(file, fileName);
if (fileids == null) {
return null;
}
int delResult = deleteFile(oldGroupName, oldFileName);
if (delResult != 0) {
return null;
}
} catch (Exception ex) {
return null;
}
return fileids;
}
public static InputStream downloadFile(String groupName, String remoteFileName) {
try {
byte[] bytes = storageClient.download_file(groupName, remoteFileName);
InputStream inputStream = new ByteArrayInputStream(bytes);
return inputStream;
} catch (Exception ex) {
return null;
}
}
public static NameValuePair[] getMetaDate(String groupName, String remoteFileName){
try{
NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
return nvp;
}catch(Exception ex){
ex.printStackTrace();
return null;
}
}
private static String getFileExt(String fileName) {
if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
return "";
} else {
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
}
}
Testing Implementation
Create a test class com.msb.MyMain:
public class MyMain {
public static void main(String[] args) {
try {
File file = new File("D:/b.png");
InputStream is = new FileInputStream(file);
String fileName = UUID.randomUUID().toString()+".png";
String[] result = FastDFSClient.uploadFile(is, fileName);
System.out.println(Arrays.toString(result));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
File Retrieval Process
Download Sequence
- The client requests the Tracker for the appropriate Storage server using the file identifier (group name and filename).
- Tracker provides an available Storage server.
- Direct communication between the client and Storage completes the download.
Code Example
Use the utility method for downloading:
try {
InputStream is = FastDFSClient.downloadFile("group1", "M00/00/00/wKg0gF3zAKCARs6kAAASjQVYlWA098.png");
OutputStream os = new FileOutputStream(new File("D:/jqk.png"));
int index = 0 ;
while((index = is.read())!=-1){
os.write(index);
}
os.flush();
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
Introduction to Nginx
Overview
FastDFS lacks built-in file access capabilities and requires external tools for HTTP image access. Nginx offers proxy and virtual host features.
Nginx is a high-performance HTTP and reverse proxy server developed by Igor Sysoev for Rambler.ru. It excels in handling concurrent connections and is a preferred alternative to Apache.
Proxy Types
Forward Proxy
A forward proxy sits between the client and target server, forwarding requests from the client to the destination server.
Reverse Proxy
A reverse proxy receives requests from the internet, forwards them to internal servers, and returns results to the client. The client interacts with the proxy, not the actual server.
Key Differences
- Location: Forward proxy is placed between client and server; reverse proxy is at the server side.
- Target: Forward proxy serves clients; reverse proxy serves servers.
Nginx Functions
- HTTP Proxying: Handles HTTP protocol traffic.
- Virtual Hosting: Listens on specific ports and serves content based on request paths.
- Load Balancing: Distributes traffic across multiple backend servers.
Installation Instructions
Install fastdfs-nginx-module
Upload fastdfs-nginx-module_v1.16.tar.gz to /usr/local/tmp
# cd /usr/local/tmp
# tar zxf fastdfs-nginx-module_v1.16.tar.gz
Modify src/config to remove 'local' from path:
Install Nginx Dependencies
# yum install -y gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel
Install Nginx
Upload nginx-1.16.1.tar.gz to /usr/local/tmp
# cd /usr/local/tmp
# tar zxf nginx-1.16.1.tar.gz
Configure Nginx
Enter Nginx directory:
# cd nginx-1.16.1
# mkdir -p /var/temp/nginx
Configure with FastDFS module:
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/usr/local/tmp/fastdfs-nginx-module/src
Compile and Install
# make
# make install
Configure fastdfs-nginx-module
Copy configuration file:
# cp /usr/local/tmp/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
Edit /etc/fdfs/mod_fastdfs.conf:
connect_timeout=10
tracker_server=192.168.93.10:22122
url_have_group_name=true
store_path0=/usr/local/fastdfs/storage/store
Copy Required Files
# cp /usr/local/tmp/FastDFS/conf/http.conf /etc/fdfs/
# cp /usr/local/tmp/FastDFS/conf/mime.types /etc/fdfs/
Create Symbolic Link
# ln -s /usr/local/fastdfs/storage/store/data/ /usr/local/fastdfs/storage/store/data/M00
Update Nginx Configuration
Edit /usr/local/nginx/conf/nginx.conf:
user root;
server {
listen 8888;
server_name localhost;
location ~/group([0-9])/M00 {
ngx_fastdfs_module;
}
}
Launch Nginx
# cd /usr/local/nginx/sbin/
# ./nginx
# ./nginx -s quit