fastdfs工具类与采坑记

一、docker安装Fastdfs

1.查找Docker Hub上的redis镜像

docker search fastdfs

2.拉取镜像

docker pull delron/fastdfs #拉取最新版本

4.使用docker镜像构建tracker容器(跟踪服务器,起到调度的作用):

docker run -dti --network=host --name tracker -v /var/fdfs/tracker:/var/fdfs -v /etc/localtime:/etc/localtime delron/fastdfs tracker

5.使用docker镜像构建storage容器(存储服务器,提供容量和备份服务):

docker run -dti  --network=host --name storage -e TRACKER_SERVER=192.168.56.1:22122 -v /var/fdfs/storage:/var/fdfs  -v /etc/localtime:/etc/localtime  delron/fastdfs storage

注意TRACKER_SERVER=外网的ip地址:22122 本机ip地址不要使用127.0.0.1
注意

. 应用系统在上传文件到FastDFS成功时将原始文件名和“文件索引(FID)”保存下来(例如:保存到数据库)。
 
二. 用户点击下载的时用Nginx的域名和FID拼出url,然后在url后面增加一个参数,指定原始文件名。例如:
http://192.168.6.124:8888/group1/M00/00/00/wKgGe15Ut3CAZcnmAA98T7dRZ0c.tar.gz?attname=shooter.tar.gz
 
三. 在Nginx上进行如下配置,这样Nginx就会截获url中的参数attname,在Http响应头里面加上字段 Content-Disposition "attachment;filename=$arg_attname"

在这里插入图片描述

server {
    
    
        listen       8888;
        server_name  localhost;
        location ~/group([0-9])/M00 {
    
    
            alias /data-fdfs/storage/data;
            add_header Content-Disposition "attachment;filename=$arg_attname";
            ngx_fastdfs_module;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
    
    
            root   html;
        }
        access_log /usr/local/nginx/logs/access.log main;
    }

进入storage容器,到storage的配置文件中配置http访问的端口,配置文件在/etc/fdfs目录下的storage.conf。
6.测试

 /usr/bin/fdfs_upload_file /etc/fdfs/client.conf test.png

二、客户端依赖

        <dependency>
            <groupId>com.roncoo</groupId>
            <artifactId>fastdfs-client-java</artifactId>
            <version>1.29</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
		<dependency>
		    <groupId>org.csource</groupId>
		    <artifactId>fastdfs-client-java</artifactId>
		    <version>1.27-RELEASE</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

三、工具类

import lombok.Data;

@Data
public class FastDFSFile {
    
    
    /**
     * 文件名字
     */
    private String name;
    /**
     * 文件内容
     */
    private byte[] content;
    /**
     * 文件扩展名
     */
    private String ext;
    /**
     * 文件MD5摘要值
     */
    private String md5;
    /**
     * 文件创建作者
     */
    private String author;

    /**
     * 文件长度
     */
    private Long size;


    public FastDFSFile(String name, byte[] content, String ext, String height, String width, String author) {
    
    
        super();
        this.name = name;
        this.content = content;
        this.ext = ext;
        this.author = author;
    }

    public FastDFSFile(String name, byte[] content, String ext) {
    
    
        super();
        this.name = name;
        this.content = content;
        this.ext = ext;
    }

    public FastDFSFile(byte[] content, String name, Long size){
    
    
        this.content = content;
        this.name = name;
        this.size = size;
    }
}

fastdfs客户端

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 上传对象存储数据 访问8888
 */

@Order(100)
@Slf4j
@Configuration
public class FastDfsClient implements ApplicationListener<ApplicationReadyEvent> {
    
    

    private static int dfsTrackerPoint;

    private static String dfsTrackerServer;

    private static int dfsConnectTimeout;

    private static int dfsNetworkTimeout;


    /**
     * 上传文件
     * @param file 文件对象
     * @param fileName 文件名
     * @return
     */
    public String uploadFile(File file, String fileName) {
    
    
        try {
    
    
            FileInputStream fis = new FileInputStream(file);
            byte[] fileBuff = null;
            if (fis != null) {
    
    
                int len = fis.available();
                fileBuff = new byte[len];
                fis.read(fileBuff);
            }
            FastDFSFile fastDFSFile = new FastDFSFile(fileName, fileBuff, FilenameUtils.getExtension(file.getName()));
            fis.close();
            String uploadFile = uploadFile(fastDFSFile);
            if(uploadFile != null){
    
    
                return uploadFile.concat("?").concat("attname=").concat(fileName);
            }
        }catch (Exception e){
    
    
             log.error("上传文件失败:{}",e);
        }
        return null;
    }


    /**
     * 下载文件
     * @param fileName
     * @return
     */
    public byte[] downloadFile(String fileName) {
    
    
        try {
    
    
            return getStorageClient1().download_file1(fileName);
        } catch (Exception e) {
    
    
            log.error("下载文件失败:{}", e);
        }
        return null;
    }




    /**
     * 下载文件
     * @param groupName
     * @param remoteFileName
     * @return
     */
    public static InputStream downFile(String groupName, String remoteFileName) {
    
    
        try {
    
    
            StorageClient storageClient = getStorageClient();
            byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
            return new ByteArrayInputStream(fileByte);
        } catch (Exception e) {
    
    
            log.error("下载文件失败:{}",e);
        }
        return null;
    }


    /**
     * 获取文件元数据
     * @param fileId 文件ID
     * @return
     */
    public Map<String,String> getFileMetadata(String fileId) {
    
    
        try {
    
    
            NameValuePair[] metaList = getStorageClient1().get_metadata1(fileId);
            if (metaList != null) {
    
    
                HashMap<String,String> map = new HashMap<>();
                for (NameValuePair metaItem : metaList) {
    
    
                     map.put(metaItem.getName(), metaItem.getValue());
                }
                return map;
            }
        } catch (Exception e) {
    
    
            log.error("获取文件元数据失败:{}", e);
        }
        return null;
    }

    /**
     * 删除文件
     * @param fileId 文件ID
     * @return 删除失败返回-1,否则返回0
     */
    public int deleteFile(String fileId) {
    
    
        try {
    
    
            return getStorageClient1().delete_file1(fileId);
        } catch (Exception e) {
    
    
            log.error("删除文件失败:{}", e);
        }
        return -1;
    }

    /**
     * 下载文件
     * @param fileId 文件ID(上传文件成功后返回的ID)
     * @param outFile 文件下载保存位置
     * @return
     */
    public int downloadFile(String fileId, File outFile) {
    
    
        FileOutputStream fileOutputStream = null;
        ByteArrayInputStream inputStream = null;
        try {
    
    
            byte[] content = getStorageClient1().download_file1(fileId);
            inputStream = new ByteArrayInputStream(content, 1, content.length);
            fileOutputStream = new FileOutputStream(outFile);
            IOUtils.copy(inputStream, fileOutputStream);
            return 0;
        } catch (Exception e) {
    
    
            log.error("下载文件失败:{}", e);
        } finally {
    
    
            if (inputStream != null) {
    
    
                try {
    
    
                    inputStream.close();
                } catch (IOException e) {
    
    
                    log.error("下载文件完毕后, 关闭输入流失败:{}", e);
                }
            }
            if (fileOutputStream != null) {
    
    
                try {
    
    
                    fileOutputStream.close();
                } catch (IOException e) {
    
    
                    log.error("下载文件完毕后, 关闭输出流失败:{}", e);
                }
            }
        }
        return -1;
    }


    /**
     * 上传文件方法
     * <p>Title: uploadFile</p>
     * <p>Description: </p>
     * @param fileName 文件全路径
     * @param extName 文件扩展名,不包含(.)
     * @param metas 文件扩展信息
     * @return
     * @throws Exception
     */
    public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
    
    
        return getStorageClient1().upload_file1(fileName, extName, metas);
    }

    public String uploadFile(String fileName) throws Exception {
    
    
        return uploadFile(fileName, null, null);
    }

    public String uploadFile(String fileName, String extName) throws Exception {
    
    
        return uploadFile(fileName, extName, null);
    }

    /**
     * 上传文件方法
     * @param fileContent 文件的内容,字节数组
     * @param extName 文件扩展名
     * @param metas 文件扩展信息
     * @return
     * @throws Exception
     */
    public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas){
    
    
        try {
    
    
            return getTrackerUrl().concat(getStorageClient1().upload_file1(fileContent, extName, metas));
        } catch (Exception e) {
    
    
            log.error("上传文件失败:{}", e);
        }
        return null;
    }

    public String uploadFile(byte[] fileContent, String fileName){
    
    
        String uploadFile = uploadFile(fileContent, null, null);
        if(uploadFile != null){
    
    
            return uploadFile.concat("?").concat("attname=").concat(fileName);
        }
        return null;
    }

    public String uploadExtName(byte[] fileContent, String extName){
    
    
        return uploadFile(fileContent, extName, null);
    }

    /**
     * 生成可以访问的url
     * @param byteFile
     * @param extName
     * @param fileName
     * @return
     */
    public String uploadFileByte(byte[] byteFile, String extName, String fileName){
    
    
        NameValuePair[] naps = new NameValuePair[1];
        naps[0] = new NameValuePair(fileName, extName);
        try {
    
    
            return getTrackerUrl().concat(getStorageClient1().upload_file1(byteFile, extName, naps));
        } catch (Exception e) {
    
    
            log.error("上传文件失败:{}", e);
        }
        return null;
    }

    /**
     * 不生成可以访问的url
     * @param byteFile
     * @param extName
     * @param fileName
     * @return
     */
    public String uploadFileByteKey(byte[] byteFile, String extName, String fileName){
    
    
        NameValuePair[] naps = new NameValuePair[1];
        naps[0] = new NameValuePair(fileName, extName);
        try {
    
    
            return getStorageClient1().upload_file1(byteFile, extName, naps);
        } catch (Exception e) {
    
    
            log.error("上传文件失败:{}", e);
        }
        return null;
    }


    /**
     * 下载文件
     * @param groupName
     * @param fileName
     * @return 二进制流
     */
    public byte[] downloadBytes(String groupName, String fileName) {
    
    
        try {
    
    
            return getStorageClient1().download_file(groupName, fileName);
        } catch (Exception e) {
    
    
            log.error("下载文件失败:{}", e);
        }
        return null;
    }

    /**
     * 文件下载
     * @param filePath 文件地址
     * @param savePath 本地保存地址
     */
    public void download(String filePath, String savePath){
    
    
        try {
    
    
            byte[] bytes = getStorageClient1().download_file1(filePath);
            IOUtils.write(bytes,new FileOutputStream(savePath));
        } catch (Exception e) {
    
    
            log.error("文件下载失败:{}",e);
        }
    }

    /**
     * 获取文件信息
     * 文件IP地址
     * String sourceIpAddr = fileInfo.getSourceIpAddr();
     * 文件大小
     * long fileSize = fileInfo.getFileSize();
     * 文件创建时间
     * Date createTimestamp = fileInfo.getCreateTimestamp();
     * 错误码
     * long crc32 = fileInfo.getCrc32();
     * @param filePath 文件的地址
     * @return
     */
    public FileInfo getFileInfo(String filePath){
    
    
        try {
    
    
            return getStorageClient1().get_file_info1(filePath);
        } catch (Exception e) {
    
    
            log.info("获取文件信息失败:{}",e);
        }
        return null;
    }

    /**
     * 上传文件
     * @param file
     * @return
     */
    public String uploadFile(FastDFSFile file){
    
    
        NameValuePair[] nameValuePairs = new NameValuePair[1];
        nameValuePairs[0] = new NameValuePair(file.getAuthor());
        try {
    
    
            return getTrackerUrl().concat(getStorageClient1().upload_file1(file.getContent(), file.getExt(),nameValuePairs));
        } catch (Exception e) {
    
    
            log.error("upload file is fail: {} ",e.getMessage());
        }
        return null;
    }


    /**
     * 下载文件
     * @param path
     * @return  文件对象
     */
    public InputStream downFile(String path){
    
    
        try {
    
    
            byte[] bytes = getStorageClient1().download_file1(path);
            return new ByteArrayInputStream(bytes);
        } catch (Exception e) {
    
    
            log.error("download file is fail : {}", e.getMessage());
        }
        return null;
    }


    /**
     *  删除文件
     * @param path
     */
    public void deleteFilePath(String path){
    
    
        try {
    
    
            getStorageClient1().delete_file1(path);
        } catch (Exception e)  {
    
    
            log.error("delete file is fail : {}",e.getMessage());
        }
    }

    /**
     * fastDFS文件上传 生成可以访问的url
     *
     * @param file 上传的文件 FastDFSFile
     * @return String 返回文件的绝对路径
     */
    public String uploadFastDFSFile(FastDFSFile file) {
    
    
        try {
    
    
            //文件扩展名
            String ext = FilenameUtils.getExtension(file.getName());
            //mata list是表文件的描述
            NameValuePair[] mata_list = new NameValuePair[3];
            mata_list[0] = new NameValuePair("fileName", file.getName());
            mata_list[1] = new NameValuePair("fileExt", ext);
            mata_list[2] = new NameValuePair("fileSize", String.valueOf(file.getSize()));
            String url = getStorageClient1().upload_file1(file.getContent(), ext, mata_list);
            return getTrackerUrl().concat(url);
        } catch (Exception e) {
    
    
           log.error("上传文件失败:{}",e);
        }
        return null;
    }

    /**
     * 不生成 可以访问的url
     * @param file
     * @return
     */
    public String uploadFastDFSFileKey(FastDFSFile file) {
    
    
        try {
    
    
            //文件扩展名
            String ext = FilenameUtils.getExtension(file.getName());
            //mata list是表文件的描述
            NameValuePair[] mata_list = new NameValuePair[3];
            mata_list[0] = new NameValuePair("fileName", file.getName());
            mata_list[1] = new NameValuePair("fileExt", ext);
            mata_list[2] = new NameValuePair("fileSize", String.valueOf(file.getSize()));
            String url = getStorageClient1().upload_file1(file.getContent(), ext, mata_list);
            return getTrackerUrl().concat(url);
        } catch (Exception e) {
    
    
            log.error("上传文件失败:{}",e);
        }
        return null;
    }


    @Value("${xxx.dfsTrackerPoint}")
    public void setDfsTrackerPoint(int dfsTrackerPoint) {
    
    
        FastDfsClient.dfsTrackerPoint = dfsTrackerPoint;
    }

    @Value("${xxx.dfsTrackerServer}")
    public void setDfsTrackerServer(String dfsTrackerServer) {
    
    
        FastDfsClient.dfsTrackerServer = dfsTrackerServer;
    }

    @Value("${xxx.dfsConnectTimeout}")
    public void setDfsConnectTimeout(int dfsConnectTimeout) {
    
    
        FastDfsClient.dfsConnectTimeout = dfsConnectTimeout;
    }

    @Value("${xxx.dfsNetworkTimeout}")
    public void setDfsNetworkTimeout(int dfsNetworkTimeout) {
    
    
        FastDfsClient.dfsNetworkTimeout = dfsNetworkTimeout;
    }

    public static StorageServer[] getStoreStorages(String groupName) throws IOException {
    
    
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerClient.getStoreStorages(trackerServer, groupName);
    }

    public static ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException {
    
    
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
    }

    public static String getTrackerUrl() throws IOException {
    
    
        return "http://" + getTrackerServer().getInetSocketAddress().getHostString().concat(":").concat("8888").concat("/");
    }

    private static StorageClient getStorageClient() throws IOException {
    
    
        TrackerServer trackerServer = getTrackerServer();
        StorageClient storageClient = new StorageClient(trackerServer, null);
        // 连接FastDFS集群,避免出现 java.io.IOException: recv package size -1 != 10 防止30秒进行重连
        //ProtoCommon.activeTest(trackerServer.getSocket());
        return storageClient;
    }

    private static TrackerClient getTrackerClient() {
    
    
        TrackerClient trackerClient = new TrackerClient();
        return trackerClient;
    }

    private static TrackerServer getTrackerServer() throws IOException {
    
    
        TrackerClient trackerClient = getTrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerServer;
    }

    private static StorageClient1 getStorageClient1() throws IOException {
    
    
        TrackerClient trackerClient = getTrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
        StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
        // 连接FastDFS集群,避免出现 java.io.IOException: recv package size -1 != 10 防止30秒进行重连
        //ProtoCommon.activeTest(trackerServer.getSocket());
        return storageClient1;
    }


    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
    
    
        try {
    
    
            Properties props = new Properties();
            props.put(ClientGlobal.PROP_KEY_TRACKER_SERVERS, dfsTrackerServer == null ? "192.168.21.1:22122" : dfsTrackerServer);
            props.put(ClientGlobal.PROP_KEY_HTTP_TRACKER_HTTP_PORT, dfsTrackerPoint == 0 ? 22122 : dfsTrackerPoint);
            props.put(ClientGlobal.PROP_KEY_CHARSET, "UTF-8");
            props.put(ClientGlobal.PROP_KEY_HTTP_SECRET_KEY, "FastDFS1234567890");
            props.put(ClientGlobal.PROP_KEY_HTTP_ANTI_STEAL_TOKEN, false);
            //加载连接信息
            ClientGlobal.initByProperties(props);
        }catch (Exception e){
    
    
            log.error("初始化配置失败:{}", e);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_32447301/article/details/108425122