欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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