图片上传业务
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客户端
- 引入依赖
<!--引入FastDFS工具类-->
<dependency>
<groupId>cn.bestwu</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27</version>
</dependency>
- 配置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
- 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.必要的图片压缩
- 依赖
<!--使用thumbnailator依赖包(图片压缩)-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
- 压缩
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;
}