Java实现图片分片上传
程序员文章站
2022-07-10 20:27:02
...
1、需求
最近前端同事想拥有一个图片素材库并针对大图实现压缩。最开始提供的接口只是简单的图片上传,实现压缩图片技术是缩略图和webp压缩并上传到ftp,这里出现一个问题前端会上传一些比较大的图片,项目中针对服务设置了超时时间,经常出现接口超时。网上有很多实现分片上传图片,自己也想着实现图片分片上传。
2、原理
客户端将图片分割成多个小的分片,然后再将这些分片一片一片的上传给服务端,服务端拿到分片后通过ftp追加最后合成一个整图。这里需要有一个唯一标识来分片属于一个整图,这边和前端约束前端生成一个唯一的标识(后端生成唯一标识响应给前端也可以)传给后端,这边通过唯一标识生成请求响应标识,前端取到之后在设置请求头,后端取请求头中的参数做区分。
3、实现
/**
* @param image
* @param imageId 唯一标识
* @param chunk 当前分片数
* @param chunk 总分片数
* @param imageName 图片名
*/
public RetInfo uploadImage(HttpServletRequest request, HttpServletResponse response,MultipartFile image, String imageId, int chunk, int chunks,String imageName) {
String rename = imageId;
if (request.getHeader("image-"+imageId) != null) {
rename = request.getHeader("image-"+imageId);
Integer size = Integer.valueOf(request.getHeader("size-" + imageId));
Integer attribute = Integer.valueOf(request.getHeader("chunk-" + imageId));
if (attribute != chunk) {
return RetInfo.failBuilder("参数非法");
}
response.setHeader("image-"+imageId,rename);
response.setHeader("chunk-"+imageId,chunk+1 + "");
response.setHeader("size-"+imageId,size + image.getSize() + "");
} else {
response.setHeader("image-"+imageId,rename);
response.setHeader("chunk-"+imageId,chunk+1 + "");
response.setHeader("size-"+imageId,image.getSize() + "");
}
。。。。。。。。
}
这里在请求中记录了下一个chunk分片数和下一次请求参数做判断,判断是否请求合法。
这里在记录下ftp工具使用。
/**
* Description: 向FTP服务器文件追加内容
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
* @param fileName 上传到FTP服务器上的文件名
* @param input 追加的文件流
* @return 成功返回true,否则返回false
*/
public static boolean appendFile(String host, int port, String username, String password, String basePath,
String filePath, String fileName, InputStream input) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);// 连接FTP服务器
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
if(basePath != null && basePath != ""){
if (!ftp.changeWorkingDirectory(basePath)) {
if (!ftp.makeDirectory(basePath)) {
return result;
}
}
}
//设置PassiveMode传输
ftp.enterLocalPassiveMode();
//设置以二进制流的方式传输
ftp.setFileType(FTP.BINARY_FILE_TYPE);
ftp.setControlEncoding("GBK");
//切换到上传目录
if (!ftp.changeWorkingDirectory(basePath + filePath)) {
//如果目录不存在创建目录
String[] dirs = filePath.split("/");
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) {
continue;
}
tempPath += "/" + dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
return result;
} else {
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
//检查远程是否存在文件
FTPFile[] fs = ftp.listFiles();
FTPFile ftpFile = null;
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
//追加
ftpFile = ff;
break;
}
}
if (ftpFile == null) {
//新增
//设置上传文件的类型为二进制类型
ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
//上传文件
if (!ftp.storeFile(fileName, input)) {
return result;
}
input.close();
} else {
//追加
long remoteSize = ftpFile.getSize();
ftp.setRestartOffset(remoteSize);
OutputStream out = ftp.appendFileStream(fileName);
if (out != null) {
byte[] bytes = new byte[1024];
int c;
while((c = input.read(bytes)) != -1){
out.write(bytes, 0, c);
}
out.flush();
out.close();
}
input.close();
}
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
压缩图片这里就不做说明了。有时间在介绍webp压缩
上面就是实现图片分片上传的方法,如果有什么不足之处或者觉得缺少了上面,可以直接评论哦,然后我会准时补上,或者给你们解决问题。
上一篇: java实现上传图片(tcp)
下一篇: java实现图片上传