图片上传业务

2019, Feb 03    

图片上传业务

1.docker搭建FastDFS

下载镜像

docker pull mypjb/fastdfs

创建fastdfs容器

docker run --add-host fastdfs.net:xxx.xxx.xxx.xxx --name fastdfs --net=host -e TRACKER_ENABLE=1 -e NGINX_PORT=81 -v /home/fastdfs:/storage/fastdfs -it mypjb/fastdfs

注:

xxx.xxx.xxx.xxx是宿主机的IP

81是访问的端口(如果搭建了网关,那么这个端口也可以关闭)

除此之外,还需要放通的端口有(一共4个端口):

8080 -tracker_http_port

12050 -tracker_server

12041 -fdfs_storaged

测试效果

找一张图片,上传到/home/fastdfs/data/00/00目录下,修改文件名为wKgByFmn1iGAUsF1AAL4cszpkW0032.jpg(如果不是这个文件名,待会儿会找不到这个文件)

访问http://xxx.xxx.xxx.xxx:81/M00/00/00/wKgByFmn1iGAUsF1AAL4cszpkW0032.jpg

**如何修改fastdfs密码**

进入容器的/usr/local/fastdfs/conf,编辑http.conf,然后重启容器(FAIl)

2.FastDFS客户端

  1. 引入依赖
<!--引入FastDFS工具类-->
	<dependency>
		<groupId>cn.bestwu</groupId>
         <artifactId>fastdfs-client-java</artifactId>
         <version>1.27</version>
     </dependency>  
  1. 配置fdfs_client.conf
connect_timeout = 2
network_timeout = 30
charset = UTF-8
# Tracker配置文件中配置的http端口
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key =dfhgTGgfh%^d3#@%
# Tracker服务器地址
tracker_server = xxx.xxx.xxx.xxx:12050
  1. Java客户短操纵fastDFS
import net.coobird.thumbnailator.Thumbnails;
import org.csource.common.MyException;
import org.junit.Test;

import java.awt.image.BufferedImage;
import java.io.*;

import org.csource.fastdfs.*;

import javax.imageio.ImageIO;

import static org.junit.Assert.*;

public class JunitTest {
    // 本地文件位置
    String local = "C:\\Users\\Liu\\Desktop\\3.jpg";
    // 声明跟踪器客户端对象
    TrackerClient trackerClient = null;
    // 声明存储器客户端对象
    StorageClient1 storageClient1 = null;
    // 声明跟踪器服务对象
    TrackerServer trackerServer = null;
    // 声明存储器服务对象
    StorageServer storageServer = null;

    @Test
    public void deleteFile() {
        int result = -1;
        try {
            // 初始化配置文件
            ClientGlobal.init("fdfs_client.conf");
            // 创建跟踪器客户端对象
            trackerClient = new TrackerClient();
            // 获取跟踪器连接
            trackerServer = trackerClient.getConnection();
            // 获取存储器客户端对象
            storageClient1 = new StorageClient1(trackerServer, storageServer);
            // 删除文件
            result = storageClient1.delete_file("picture", "M00/00/00/rBsABFxQMJWAe70nAADsPx_Wbzo137.png");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
        System.out.println(result);

    }

    @Test
    public void testUpload() {
        try {
            // 初始化配置文件
            ClientGlobal.init("fdfs_client.conf");
            // 创建跟踪器客户端对象
            trackerClient = new TrackerClient();
            // 获取跟踪器连接
            trackerServer = trackerClient.getConnection();
            // 获取存储器客户端对象
            storageClient1 = new StorageClient1(trackerServer, storageServer);
            // 上传文件,返回文件标识,也支持上传二进制byte数组
            String index = storageClient1.upload_file1(local, null, null);
            // 查看标识
            System.out.println(index);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }    

}

3.并发传图

这里的一个坑,就是FastDFS客户端是线程不安全的

4.必要的图片压缩

  1. 依赖
<!--使用thumbnailator依赖包(图片压缩)-->
<dependency>
	<groupId>net.coobird</groupId>
	<artifactId>thumbnailator</artifactId>
	<version>0.4.8</version>
</dependency>
  1. 压缩
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * ImgCompress
 *
 * @author Flynn
 * @version 1.0
 * @description 图片压缩
 * @email liufenglin@163.com
 */
public class ImgCompress {
    public static final Logger logger = LoggerFactory.getLogger("ImgCompress");
    /**
     * 控制是否进行图片压缩
     */
    private static final boolean isCompressed = true;

    public static byte [] compress(byte [] buffer, String type) {
        if (isCompressed) {
             // 进行图片压缩
            return doCompress(buffer, type);
        } else {
            return buffer;
        }
    }

    private static byte [] doCompress(byte [] imageBytes, String type) {
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / 1024);
        try {
            logger.info("<<<开始压缩图片了,目标大小:" + desFileSize(srcSize) + "kb");
            while (imageBytes.length > desFileSize(srcSize) * 1024) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream)
                        .scale(accuracy)
                        .outputQuality(accuracy)
                        .toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
                logger.info("<<<开始压缩图片了,临时压缩后的大小:" + imageBytes.length + "b");
            }
            logger.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb",
                    System.currentTimeMillis(), srcSize / 1024, imageBytes.length < 1024 ? (imageBytes.length+0.0)/1024 : imageBytes.length / 1024);
        } catch (Exception e) {
            logger.error("【图片压缩】msg=图片压缩失败!", e);
        }
        return imageBytes;
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }

    private static long desFileSize(long size) {
        long kbSize = size / 1024;
        long result = 0;
        if (kbSize > 10 * M_SIZE_KB) {
            result =  kbSize /100;
        } else if (kbSize > 5 * M_SIZE_KB) {
            result = kbSize / 4;
        } else if (kbSize > 2 * M_SIZE_KB) {
            result = kbSize / 3;
        } else {
            result = kbSize / 2;
        }
        return result == 0 ? 1L : result;
    }

    private static long M_SIZE_KB = 1024;
}