FTP断点续传卡死的问题。

摆渡者 发布于 2015/07/29 10:24
阅读 1K+
收藏 0

用Apache Commons-Net包中的FtpClient做文件上传,从手机上传到服务器,手机使用WiFi连接,Server是Linux的vsftpd搭建的。 有以下特殊情况:上传文件到一半的时候,手动关掉WiFi致其上传失败,之后重新打开WiFi,重新初始化FtpClient并重新连接,接下来进入断点续传模式,问题是在断点续传时会卡死在storeFileStream()方法中,无论多久都没有反应,使用FTP工具软件FileZilla连接上FTP后也不能下载该文件下来。我在客户端设置了连接超时后,每次都报SocketTimeoutException并尝试重新建立连接,但是每次都到storeFileStream()这里就又卡死了。检查FTP服务器,发现文件存在,但是被进程占用。

是不是当手动关掉WiFi后,FTP服务器并不知道连接已经断开,于是不认为客户端已经完成文件读写操作,因此没有关闭该文件,于是其它的FTP连接就不能进行读写?在第一次上传时断开WiFi,客户端也没法关闭之前的连接了,这时候已经打开的连接还有办法释放吗?服务器端需要做什么处理吗?比如设置超时就释放资源?

下面是上传的部分代码(VideoStatus是一个枚举类):


public static VideoStatus uploadFromBreakPoint(String videoName, File videoFile) {
	String tmpName = videoName + ".tmp";
	FTPFile[] files = null;
	try {
		files = mFtpClient.listFiles(tmpName);
	} catch (Exception e) {
		return VideoStatus.UPLOAD_FAILED;
	}
	if (files == null || files.length == 0) {
		String log = "UploadFromBreakPoint: Remote file " + videoName + " does not exists!";
		CommonUtils.printLog(log);
		return VideoStatus.UPLOAD_FAILED;
	}

	String remoteName = files[0].getName();
	long remoteSize = files[0].getSize();
	long localSize = videoFile.length();
	String log = "UploadFromBreakPoint: File " + remoteName + " exists in FTP. RemoteLength="
			+ remoteSize + ", LocalLength=" + localSize;
	CommonUtils.printLog(log);
	
	if (remoteSize > localSize) {
		return VideoStatus.UPLOAD_FAILED;
	} else if (remoteSize == localSize) {
		// Rename remote file, remove ".tmp" suffix
		renameRemoteFile(remoteName, videoName);
		return VideoStatus.UPLOAD_SUCCESS;
	}

	// Try to move position to restart uploading from break.
	log = "UploadFromBreakPoint: Uploading " + remoteName + " from break point(" + remoteSize + ")";
	CommonUtils.printLog(log);
	long beforeUpload = System.currentTimeMillis();
	InputStream is = null;
	OutputStream output = null;
	try {
		is = new FileInputStream(videoFile);
		if(is.skip(remoteSize) == remoteSize){
			mFtpClient.setRestartOffset(remoteSize);
			
			int len = 0;
			long sum = remoteSize;
			long fileLength = videoFile.length();
			// Start from break.
			output = mFtpClient.appendFileStream(remoteName);
			
			byte[] buffer = new byte[1024 * 100];
			
			log = "UploadFromBreakPoint: File uploading. File=" + videoName
					+ ", begin read FileInputStream";
			CommonUtils.printLog(log);

			boolean printFlag = true;
			while ((len = is.read(buffer)) > 0) {
				output.write(buffer, 0, len);
				sum += len;
				output.flush();
			}
			output.close();
			
			if (mFtpClient.completePendingCommand())
			{
				long cost = System.currentTimeMillis() - beforeUpload;
				long speed = videoFile.length() / cost;
				double lenthMB = videoFile.length() / 1024 / 1024.0;
				DecimalFormat df = new DecimalFormat("#.00");
				log = "UploadFromBreakPoint: File uploaded. File=" + videoName + ", Length="
						+ df.format(lenthMB) + "MB, Cost=" + (cost / 1000)
						+ "s, AvgSpeed=" + speed + "KB/s";
				CommonUtils.printLog(log);

				renameRemoteFile(tmpName, videoName);
				log = "UploadFromBreakPoint: File renamed. File=" + videoName;
				CommonUtils.printLog(log);
				// Upload Success
				return VideoStatus.UPLOAD_SUCCESS;
			}
			else
			{
				String ftpReply = mFtpClient.getReplyString();
				log = "UploadFromBeginning: Upload " + videoName + " failed. FTPReplyString: " + ftpReply;
				CommonUtils.printLog(log);
			}
		}
	} catch (Exception e1) {
		// Upload failed
		forceCloseOutPutStream(output);
		String log3 = "UploadFromBreakPoint: Failed to upload " + videoName + ", Exception: " + e1.getMessage();
		CommonUtils.printLog(log3);
		CommonUtils.printStackTrace(e1);
	} finally {
		FtpUtils.forceCloseInputStream(is);
	}
	return VideoStatus.UPLOAD_FAILED;
}





加载中
返回顶部
顶部