• FastDFS安装与Springboot图片上传


    源码下载

    Linux安装FastFDS

    准备基础环境
    1.因为fastdfs是C语言写的,所以我们需要安装gcc环境。
      yum -y install gcc-c++
    2.fastdfs依赖libevent库,需要安装它。
      yum -y install libevent
    3.安装 Perl 库,nginx 的 http 模块使用 pcre 来解析正则表达式
      yum install -y pcre pcre-devel
    4.安装zlib 库,它提供了很多种压缩和解压缩的方式
      yum install -y zlib zlib-devel
    5.安装OpenSSL,它是一个强大的安全套接字层密码库
      yum install -y openssl openssl-devel
    上传安装文件

     

    安装libfastcommon
    1.解压
      tar -zxvf libfastcommon-1.0.7.tar.gz
    2.进入解压后的目录,编译并安装
      cd libfastcommon-1.0.7 && ./make.sh && ./make.sh install

    3.将这个文件copy到/usr/lib目录
      cp /usr/lib64/libfastcommon.so /usr/lib

    安装fastdfs_v5.05 (tracker+storage)
    1.解压
      tar -zxvf FastDFS_v5.05.tar.gz
    2.编译并安装
      cd FastDFS && ./make.sh && ./make.sh install

    3.将fastdfs/conf的配置文件全copy/etc/fdfs目录里面

    安装tracker
    指定追踪器的文件和日志存储位置       vim /etc/fdfs/tracker.conf

    安装storage

    指定存储器的文件和日志存储位置以及与追踪器通信的所在地址      vim /etc/fdfs/storage.conf

    启动服务

    启动追踪器(几乎秒开)
    /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf

    启动存储器 (这个时间会稍微久一点,它比tracker做的事情要多一些,我这边大概花了3s)
    /usr/bin/fdfs_storaged /etc/fdfs/storage.conf

    测试是否安装成功

    3. 上传文件

    创建测试文件
    [root@node1 client]# vim /wulei.html
    [root@node1 client]# cat /wulei.html
    这是我的测试文件 wulei.html 。
    上传测试文件
    
    [root@node1 client]# /usr/bin/fdfs_test /etc/fdfs/client.conf upload /wulei.html 
    This is FastDFS client test program v5.05
    
    Copyright (C) 2008, Happy Fish / YuQing
    
    FastDFS may be copied only under the terms of the GNU General
    Public License V3, which may be found in the FastDFS source kit.
    Please visit the FastDFS Home Page http://www.csource.org/ 
    for more detail.
    
    [2020-01-15 08:50:43] DEBUG - base_path=/usr/local/wulei/fastdfs/FastDFS/client, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0
    
    tracker_query_storage_store_list_without_group: 
        server 1. group_name=, ip_addr=192.168.209.101, port=23000
    
    group_name=group1, ip_addr=192.168.209.101, port=23000
    storage_upload_by_filename
    group_name=group1, remote_filename=M00/00/00/wKjRZV4fGLOAWuU6AAAAKOg17r881.html
    source ip address: 192.168.209.101
    file timestamp=2020-01-15 08:50:43
    file size=40
    file crc32=3895848639
    example file url: http://192.168.209.101/group1/M00/00/00/wKjRZV4fGLOAWuU6AAAAKOg17r881.html
    storage_upload_slave_by_filename
    group_name=group1, remote_filename=M00/00/00/wKjRZV4fGLOAWuU6AAAAKOg17r881_big.html
    source ip address: 192.168.209.101
    file timestamp=2020-01-15 08:50:43
    file size=40
    file crc32=3895848639
    example file url: http://192.168.209.101/group1/M00/00/00/wKjRZV4fGLOAWuU6AAAAKOg17r881_big.html
    
    看到上面 粉橙色文字 说明上传成功了,我们可以去到这个目录查看文件。
    [root@node1 client]# cd /usr/local/wulei/fastdfs/FastDFS/storage/data/00/00
    [root@node1 00]# ll
    total 16
    -rw-r--r--. 1 root root 40 Jan 15 08:50 wKjRZV4fGLOAWuU6AAAAKOg17r881_big.html
    -rw-r--r--. 1 root root 49 Jan 15 08:50 wKjRZV4fGLOAWuU6AAAAKOg17r881_big.html-m
    -rw-r--r--. 1 root root 40 Jan 15 08:50 wKjRZV4fGLOAWuU6AAAAKOg17r881.html
    -rw-r--r--. 1 root root 49 Jan 15 08:50 wKjRZV4fGLOAWuU6AAAAKOg17r881.html-m
    [root@node1 00]# 

     安装nginx的fastdfs插件

    上面就完成了fastdfs的安装,但此时文件的url还是无法访问的,我们需要配置nginx的fastdfs模块来代理。 

    安装fastdfs-nginx-module.

    1.解压
      tar -zxvf fastdfs-nginx-module_v1.16.tar.gz
    2.修改 fastdfs-nginx-module 配置文件
      vim fastdfs-nginx-module/src/config

    3.修改 mod_fastdfs.conf 配置
      cp ./fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs
      vim /etc/fdfs/mod_fastdfs.conf

    # 跟踪器地址
    tracker_server=192.168.209.101:22122
    
    # 存储器端口
    storage_server_port=23000
    
    # 存储器的组名称
    group_name=group1
    
    # 若文件url包含组名称则为true,反之false。我们刚才的就包含
    url_have_group_name = true
    
    
    # 存储器存文件的地址
    store_path0=/usr/local/wulei/fastdfs/FastDFS/storage

    安装nginx

    1.解压
      tar -zxvf nginx-1.14.1.tar.gz
    2.nginx添加fastdfs-nginx-module模块
      cd nginx-1.14.1 && ./configure --add-module=/usr/local/wulei/fastdfs/fastdfs-nginx-module/src

    我们也可以同时指定安装目录  cd nginx-1.14.1 && ./configure --add-module=/usr/local/wulei/fastdfs/fastdfs-nginx-module/src --prefix=/usr/local/wulei/fastdfs/nginx-1.14.1 我们需要在指定目录 mkdir logs, 因为他不会自动生成。
    3.编译并安装,此时会生成 sbin目录  
      make && make install 

    4. 修改配置文件  vim /usr/local/nginx/conf/nginx.conf
    location /group1/M00/{
      ngx_fastdfs_module;
    }

    5. 启动 /usr/local/nginx/sbin/nginx

     Springboot实现图片上传

    导入依赖

        <dependencies>
            <!--web-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- 页面薄板 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <!-- 文件服务器客户端 -->
            <dependency>
                <groupId>com.github.tobato</groupId>
                <artifactId>fastdfs-client</artifactId>
                <version>1.26.1-RELEASE</version>
            </dependency>
        </dependencies>
    View Code

    application.yml

    server:
      port: 8081
    
    spring:
      # ==============================================================
      # 静态资源配置(页面静态化缓存,不需要访问服务端)
      resources:
        # 页面在浏览器的缓存时间
        cache:
          cachecontrol:
            max-age: 3600
        # static-locations:表示需要放行的静态资源
        static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/templates/
        #启动静态资源文件处理,默认为true
        add-mappings: true
        chain:
          cache: true
          enabled: true
          # 对静态资源进行压缩
          gzipped: true
          html-application-cache: true
      # thymeleaf模板参数配置
      thymeleaf:
        cache: false
        content-type: text/html
        enabled: true
        encoding: UTF-8
        mode: HTML5
        prefix: classpath:/templates/
        suffix: .html
      servlet:
        multipart:
          #单个文件最大尺寸
          max-file-size: 10mb
          #一个请求文件的最大尺寸
          max-request-size: 50mb
          
    fdfs:
      # 读取inputsream阻塞时间 
      so-timeout: 1501
      connect-timeout: 601
      # 缩略图
      thumb-image:
         250
        height: 250
      # tracker地址
      tracker-list: 192.168.200.100:22122
      # 通过nginx 访问地址 
      resHost: 192.168.200.100
      storagePort: 80
      #获取连接池最大数量
      pool:
        max-total: 200 
      
    View Code

    fastdfs工具类

    import java.math.BigDecimal;
    import java.util.Arrays;
    import java.util.List;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.StringUtils;
    import org.springframework.web.multipart.MultipartFile;
    import com.github.tobato.fastdfs.domain.StorePath;
    import com.github.tobato.fastdfs.domain.ThumbImageConfig;
    import com.github.tobato.fastdfs.service.FastFileStorageClient;
    
    import cn.wulei.conf.ApplicationProperties;
    
    public class FastUtils {
    
        private static Logger logger = LoggerFactory.getLogger(FastUtils.class);
    
        private  static ApplicationProperties applicationProperties= SpringUtil.getBean(ApplicationProperties.class);
        //fastDFS
        private  static FastFileStorageClient storageClient = SpringUtil.getBean(FastFileStorageClient.class);
        //fastDFS 缩略图配置
        private  static ThumbImageConfig thumbImageConfig= SpringUtil.getBean(ThumbImageConfig.class);
    
        private static final String FEN = "/";
    
        /**
         * 支持上传的文件类型
         */
        private static final List<String> SUFFIXES = Arrays.asList("png", "jpeg", "jpg", "docx", "doc", "xls", "xlsx", "pdf", "txt");
    
    
        /**
         * fastDFS文件存储
         *
         * @param file
         * @param thumbImageFlag 是否创建缩略图
         * @return
         */
        public static UploadFileVo uploadFile(MultipartFile file, boolean thumbImageFlag) {
            UploadFileVo fileVo = new UploadFileVo();
            try {
                //http配置
                String http = applicationProperties.getResHost();
    
                if (StringUtils.isEmpty(http)) {
                    throw new RuntimeException("httpProperties 配置错误!");
                }
                // 原名称
                String fileName = file.getOriginalFilename();
                fileVo.setFileName(fileName);
                //后缀
                String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
                fileVo.setExtension(extension);
                if (!SUFFIXES.contains(extension)) {
                    throw new RuntimeException("上传文件类型不匹配");
                }
    
                //文件大小
                fileVo.setFileSize(file.getSize());
                fileVo.setFileSizeStr(getPrintSize(file.getSize()));
    
                //文件上传
                StorePath storePath = null;
                if (thumbImageFlag) {
                    // 上传图片并且生成缩略图
                    storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(), extension, null);
                    //原图
                    fileVo.setFileUrl(http +FEN+ storePath.getFullPath());
                    //缩略图
                    fileVo.setThumbImageUrl(http +FEN+ thumbImageConfig.getThumbImagePath(storePath.getFullPath()));
                } else {
                    // 上传文件
                    storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), extension, null);
                    //文件地址
                    fileVo.setFileUrl(http +FEN+  storePath.getFullPath());
                }
    
                return fileVo;
            } catch (Exception e) {
                logger.info("func[uploadFile]  Exception [文件上传异常: {} - {}] stackTrace[{}]", e.getCause(), e.getMessage(), Arrays.deepToString(e.getStackTrace()));
                fileVo.setErrorMsg("上传异常:" + e.getMessage());
                return fileVo;
            }
        }
    
    
        /**
         * 删除文件
         */
        public static  boolean deleteFile(String path) {
            try {
                String fullPath = getfullPath(path);
                storageClient.deleteFile(fullPath);
                return true;
            } catch (Exception e) {
                logger.info("func[deleteFile] path={} Exception [{} - {}] stackTrace[{}]", path, e.getCause(), e.getMessage(), Arrays.deepToString(e.getStackTrace()));
                return false;
            }
        }
    
        /**
         * 删除缩略图
         */
        public static   boolean deleteThumbImage(String path) {
            try {
                String fullPath = getfullPath(path);
                //获取缩略图地址
                fullPath = thumbImageConfig.getThumbImagePath(fullPath);
                storageClient.deleteFile(fullPath);
                return true;
            } catch (Exception e) {
                logger.info("func[deleteThumbImage] path={} Exception [{} - {}] stackTrace[{}]", path, e.getCause(), e.getMessage(), Arrays.deepToString(e.getStackTrace()));
                return false;
            }
        }
    
        //获取文件相对地址
        private static String getfullPath(String path) {
            String fullPath;
            if (path.indexOf("http") != -1) {
                fullPath = path.substring(path.indexOf("group"));
            } else {
                fullPath = path;
            }
            return fullPath;
        }
    
        /**
         * 返回文件大小字符
         *
         * @param size
         * @return
         */
        public static String getPrintSize(long size) {
            // 如果字节数少于1024,则直接以B为单位,否则先除于1024,后3位因太少无意义
            double value = (double) size;
            if (value < 1024) {
                return value+ "B";
            } else {
                value = BigDecimal.valueOf(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
            }
            // 如果原字节数除于1024之后,少于1024,则可以直接以KB作为单位
            // 因为还没有到达要使用另一个单位的时候
            // 接下去以此类推
            if (value < 1024) {
                return value + "KB";
            } else {
                value = BigDecimal.valueOf(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
            }
            if (value < 1024) {
                return value + "MB";
            } else {
                // 否则如果要以GB为单位的,先除于1024再作同样的处理
                value = BigDecimal.valueOf(value / 1024).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
                return value+ "GB";
            }
        }
    }
    View Code

    开启配置

    @SpringBootApplication
    // fastdfs启动配置
    @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
    @Import(FdfsClientConfig.class) 
    public class Main {
    
        final static Logger logger = LoggerFactory.getLogger(Main.class);
    
        public static void main(String[] args) {
            SpringApplication.run(Main.class, args);
            logger.info("========== APPLICATION START SUCCESS ==========");
    
        }
    }
    View Code

    别忘了防火墙开启   tracker   storage   nginx   的端口再测试。

  • 相关阅读:
    代码重构编译---make
    clickhouse日期函数
    连续登陆天数+最大登陆天数
    clickhouse基本使用
    数组
    CK优化
    Hive查询优化~布隆过滤器使用
    Presto常见问题优化
    Presto原理解析
    几种排序说明
  • 原文地址:https://www.cnblogs.com/wlwl/p/12199053.html
Copyright © 2020-2023  润新知