前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ftp工具类:上传与下载文件

ftp工具类:上传与下载文件

作者头像
全栈程序员站长
发布2022-08-26 13:39:58
3.7K0
发布2022-08-26 13:39:58
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

准备工作

服务器已经配置好ftp服务

linux服务器搭建ftp服务: https://program.blog.csdn.net/article/details/88825921

需要用到的jar包:

代码语言:javascript
复制
<dependency>
	<groupId>commons-net</groupId>
	<artifactId>commons-net</artifactId>
	<version>3.3</version>
</dependency>

配置文件

  • application.yml
代码语言:javascript
复制
# 配置ftp服务器信息
ftp: 
  # ftp服务器的IP地址
  url: 127.0.0.0
  # 默认端口是21
  port: 21
  username: ftpuser
  password: ftpuser
  # ftp服务器存放文件的路径
  remotePath: /data/ftp
  # 本地需要上传的文件的路径
  localDir: D:/test
  # ftp上文件下载到本地存放的路径
  downDir: D:/test
  • FtpConfig配置信息类
代码语言:javascript
复制
@Getter
@Component
public class FtpConfig { 
   
	/** * ftp服务器地址 */
	@Value("${ftp.url}")
	private String url;
	
	/** * ftp服务器端口 */
	@Value("${ftp.port}")
	private int port;
	
	/** * ftp服务器用户名 */
	@Value("${ftp.username}")
	private String username;
	
	/** * ftp服务器密码 */
	@Value("${ftp.password}")
	private String password;
	
	/** * ftp服务器存放文件的路径 */
	@Value("${ftp.remotePath}")
	private String remotePath;
	
	/** * 本地需要上传的文件的路径 */
	@Value("${ftp.localDir}")
	private String localDir;
	
	/** * 下载文件时,存放在本地的路径 */
	@Value("${ftp.downDir}")
	private String downDir;
	
}

工具类FtpUtil内容

代码语言:javascript
复制
@Slf4j(topic="文件上传/下载===ftp服务器:")
public class FtpUtil { 
   
	private static FTPClient mFTPClient = new FTPClient();
	private static FtpUtil ftp = new FtpUtil();
	
	public FtpUtil() { 
   
		// 在控制台打印操作过程
		 mFTPClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
	}


	/** * 上传文件到ftp服务器 */
	public static boolean ftpUpload(String fileName, String ftpUrl, int ftpPort,
			String ftpUsername, String ftpPassword, String ftpLocalDir, String ftpRemotePath) { 
   
		boolean result = false;
		try { 
   
			boolean isConnection = ftp.openConnection(ftpUrl, ftpPort, ftpUsername, ftpPassword);
			if (isConnection) { 
   
				boolean isSuccess = ftp.upload(ftpRemotePath, ftpLocalDir + "/" + fileName);
				if (isSuccess) { 
   
					log.info("文件上传成功!");
					result = true;
				} else { 
   
					log.info("文件上传失败!");
					result = false;
				}
				ftp.logout();
			} else { 
   
				log.info("链接ftp服务器失败,请检查配置信息是否正确!");
				result = false;
			}

		} catch (SocketException e) { 
   
			e.printStackTrace();
		} catch (IOException e) { 
   
			e.printStackTrace();
		}
		return result;
	}

	/** * 从ftp服务器下载文件到本地 */
	public static boolean ftpDownload(String fileName, String ftpUrl, int ftpPort,
			String ftpUsername, String ftpPassword, String ftpRemotePath, String ftpDownDir) { 
   
		boolean result = false;
		try { 
   
			boolean isConnection = ftp.openConnection(ftpUrl, ftpPort, ftpUsername, ftpPassword);
			if (isConnection) { 
   
				boolean isDownloadOk = ftp.downLoad(fileName, ftpDownDir);
				boolean isCreateOk = ftp.createDirectory(ftpRemotePath, ftp.mFTPClient);
				if (isDownloadOk && isCreateOk) { 
   
					log.info("文件下载成功!");
					result = true;
				} else { 
   
					log.info("文件下载失败!");
					result = false;
				}
				ftp.logout();
			} else { 
   
				log.info("链接ftp服务器失败,请检查配置信息是否正确!");
				result = false;
			}

		} catch (SocketException e) { 
   
			e.printStackTrace();
		} catch (IOException e) { 
   
			e.printStackTrace();
		}
		return result;

	}

	/** * 连接ftp服务器 * * @param host * ip地址 * @param port * 端口号 * @param account * 账号 * @param pwd * 密码 * @return 是否连接成功 * @throws SocketException * @throws IOException */
	private boolean openConnection(String host, int port, String account, String pwd)
			throws SocketException, IOException { 
   
		mFTPClient.setControlEncoding("UTF-8");
		mFTPClient.connect(host, port);

		if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) { 
   
			mFTPClient.login(account, pwd);
			if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) { 
   
				System.err.println(mFTPClient.getSystemType());
				FTPClientConfig config = new FTPClientConfig(mFTPClient.getSystemType().split(" ")[0]);
				config.setServerLanguageCode("zh");
				mFTPClient.configure(config);
				return true;
			}
		}
		disConnection();
		return false;
	}

	/** * 登出并断开连接 */
	public void logout() { 
   
		System.err.println("logout");
		if (mFTPClient.isConnected()) { 
   
			System.err.println("logout");
			try { 
   
				mFTPClient.logout();
				disConnection();
			} catch (IOException e) { 
   
				e.printStackTrace();
			}
		}
	}

	/** * 断开连接 */
	private void disConnection() { 
   
		if (mFTPClient.isConnected()) { 
   
			try { 
   
				mFTPClient.disconnect();
			} catch (IOException e) { 
   
				e.printStackTrace();
			}
		}
	}

	/** * 下载文件到本地地址 * * @param remotePath * 远程地址 * @param loacal * 本地地址 * @throws IOException */
	public boolean downLoad(String remotePath, String localDir) throws IOException { 
   
		// 进入被动模式
		mFTPClient.enterLocalPassiveMode();
		// 以二进制进行传输数据
		mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
		FTPFile[] ftpFiles = mFTPClient.listFiles(remotePath);
		if (ftpFiles == null || ftpFiles.length == 0) { 
   
			log.info("远程文件不存在");
			return false;
		} else if (ftpFiles.length > 1) { 
   
			log.info("远程文件是文件夹");
			return false;
		}
		long lRemoteSize = ftpFiles[0].getSize();
		// 本地文件的地址
		File localFileDir = new File(localDir);
		if (!localFileDir.exists()) { 
   
			localFileDir.mkdirs();
		}
		File localFile = new File(localFileDir, ftpFiles[0].getName());
		long localSize = 0;
		FileOutputStream fos = null;
		if (localFile.exists()) { 
   
			if (localFile.length() == lRemoteSize) { 
   
				System.err.println("已经下载完毕");
				return true;
			} else if (localFile.length() < lRemoteSize) { 
   
				// 要下载的文件存在,进行断点续传
				localSize = localFile.length();
				mFTPClient.setRestartOffset(localSize);
				fos = new FileOutputStream(localFile, true);
			}
		}
		if (fos == null) { 
   
			fos = new FileOutputStream(localFile);
		}
		InputStream is = mFTPClient.retrieveFileStream(remotePath);
		byte[] buffers = new byte[1024];
		long step = lRemoteSize / 10;
		long process = localSize / step;
		int len = -1;
		while ((len = is.read(buffers)) != -1) { 
   
			fos.write(buffers, 0, len);
			localSize += len;
			long newProcess = localSize / step;
			if (newProcess > process) { 
   
				process = newProcess;
				System.err.println("下载进度:" + process);
			}
		}
		is.close();
		fos.close();
		boolean isDo = mFTPClient.completePendingCommand();
		if (isDo) { 
   
			System.err.println("下载成功");
		} else { 
   
			System.err.println("下载失败");
		}
		return isDo;

	}

	/** * 创建远程目录 * * @param remote * 远程目录 * @param ftpClient * ftp客户端 * @return 是否创建成功 * @throws IOException */
	public boolean createDirectory(String remote, FTPClient ftpClient) throws IOException { 
   
		String dirctory = remote.substring(0, remote.lastIndexOf("/") + 1);
		if (!dirctory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(dirctory)) { 
   
			int start = 0;
			int end = 0;
			if (dirctory.startsWith("/")) { 
   
				start = 1;
			}
			end = dirctory.indexOf("/", start);
			while (true) { 
   
				String subDirctory = remote.substring(start, end);
				if (!ftpClient.changeWorkingDirectory(subDirctory)) { 
   
					if (ftpClient.makeDirectory(subDirctory)) { 
   
						ftpClient.changeWorkingDirectory(subDirctory);
					} else { 
   
						System.err.println("创建目录失败");
						return false;
					}
				}
				start = end + 1;
				end = dirctory.indexOf("/", start);
				if (end <= start) { 
   
					break;
				}
			}
		}
		return true;
	}

	/** * 上传的文件 * * @param remotePath * 上传文件的路径地址(文件夹地址) * @param localPath * 本地文件的地址 * @throws IOException * 异常 */
	public boolean upload(String remotePath, String localPath) throws IOException { 
   
		// 进入被动模式
		mFTPClient.enterLocalPassiveMode();
		// 以二进制进行传输数据
		mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
		File localFile = new File(localPath);
		if (!localFile.exists()) { 
   
			System.err.println("本地文件不存在");
			return false;
		}
		String fileName = localFile.getName();
		if (remotePath.contains("/")) { 
   
			boolean isCreateOk = createDirectory(remotePath, mFTPClient);
			if (!isCreateOk) { 
   
				System.err.println("文件夹创建失败");
				return false;
			}
		}

		// 列出ftp服务器上的文件
		FTPFile[] ftpFiles = mFTPClient.listFiles(remotePath);
		long remoteSize = 0l;
		String remoteFilePath = remotePath + "/" + fileName;
		if (ftpFiles.length > 0) { 
   
			FTPFile mFtpFile = null;
			for (FTPFile ftpFile : ftpFiles) { 
   
				if (ftpFile.getName().endsWith(fileName)) { 
   
					mFtpFile = ftpFile;
					break;
				}
			}
			if (mFtpFile != null) { 
   
				remoteSize = mFtpFile.getSize();
				if (remoteSize == localFile.length()) { 
   
					System.err.println("文件已经上传成功");
					return true;
				}
				if (remoteSize > localFile.length()) { 
   
					if (!mFTPClient.deleteFile(remoteFilePath)) { 
   
						System.err.println("服务端文件操作失败");
					} else { 
   
						boolean isUpload = uploadFile(remoteFilePath, localFile, 0);
						System.err.println("是否上传成功:" + isUpload);
					}
					return true;
				}
				if (!uploadFile(remoteFilePath, localFile, remoteSize)) { 
   
					System.err.println("文件上传成功");
					return true;
				} else { 
   
					// 断点续传失败删除文件,重新上传
					if (!mFTPClient.deleteFile(remoteFilePath)) { 
   
						System.err.println("服务端文件操作失败");
					} else { 
   
						boolean isUpload = uploadFile(remoteFilePath, localFile, 0);
						System.err.println("是否上传成功:" + isUpload);
					}
					return true;
				}
			}
		}

		boolean isUpload = uploadFile(remoteFilePath, localFile, remoteSize);
		System.err.println("是否上传成功:" + isUpload);
		return isUpload;
	}

	/** * 上传文件 * * @param remoteFile * 包含文件名的地址 * @param localFile * 本地文件 * @param remoteSize * 服务端已经存在的文件大小 * @return 是否上传成功 * @throws IOException */
	private boolean uploadFile(String remoteFile, File localFile, long remoteSize) throws IOException { 
   
		long step = localFile.length() / 10;
		long process = 0;
		long readByteSize = 0;
		RandomAccessFile randomAccessFile = new RandomAccessFile(localFile, "r");
		OutputStream os = mFTPClient.appendFileStream(remoteFile);
		if (remoteSize > 0) { 
   
			// 已经上传一部分的时候就要进行断点续传
			process = remoteSize / step;
			readByteSize = remoteSize;
			randomAccessFile.seek(remoteSize);
			mFTPClient.setRestartOffset(remoteSize);
		}
		byte[] buffers = new byte[1024];
		int len = -1;
		while ((len = randomAccessFile.read(buffers)) != -1) { 
   
			os.write(buffers, 0, len);
			readByteSize += len;
			long newProcess = readByteSize / step;
			if (newProcess > process) { 
   
				process = newProcess;
				System.err.println("当前上传进度为:" + process);
			}
		}
		os.flush();
		randomAccessFile.close();
		os.close();
		boolean result = mFTPClient.completePendingCommand();
		return result;
	}

}

访问测试

代码语言:javascript
复制
@RestController
@RequestMapping(value = "/ftp")
@Slf4j(topic="请求ftp服务器")
public class FtpController { 
   
	@Autowired
	FtpConfig ftpConfig;

	@GetMapping("/upload")
	public String upload() { 
   
		String fileName = "uploadfile.txt";
		boolean result = FtpUtil.ftpUpload(fileName, ftpConfig.getUrl(),ftpConfig.getPort(),ftpConfig.getUsername(),
				ftpConfig.getPassword(), ftpConfig.getLocalDir(), ftpConfig.getRemotePath());
		if (result) { 
   
			log.info("=======上传文件"+ fileName +"成功=======");
		} else { 
   
			log.info("=======上传文件"+ fileName +"失败=======");
		}
		return result?"上传成功":"上传失败";

	}

	@GetMapping("/download")
	public String download(){ 
   
		String fileName = "welcome.txt";
		boolean result = FtpUtil.ftpDownload(fileName, ftpConfig.getUrl(),ftpConfig.getPort(),ftpConfig.getUsername(),
				ftpConfig.getPassword(), ftpConfig.getRemotePath(), ftpConfig.getLocalDir() );
		if (result) { 
   
			log.info("=======下载文件"+ fileName +"成功=======");
		} else { 
   
			log.info("=======下载文件"+ fileName +"失败=======");
		}
		return result?"下载成功":"下载失败";
	}
	
}

测试结果1: 上传成功

测试结果2: 下载成功

代码 github 地址:https://github.com/mmzsblog/springboot-FtpUtil

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/144024.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备工作
    • 服务器已经配置好ftp服务
      • 需要用到的jar包:
        • 配置文件
        • 工具类FtpUtil内容
        • 访问测试
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档