Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

File Upload and Download Process with FastDFS

Tech 2

Upload Flow

  1. The client contacts the Tracker server.
  2. Tracker responds with the IP adress and port of a Storage server.
  3. The client communicates directly with the Storage server to send the file content and metadata.
  4. 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

  1. The client requests the Tracker for the appropriate Storage server using the file identifier (group name and filename).
  2. Tracker provides an available Storage server.
  3. 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

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.