解决FTP客户端文件断点续传过程中服务器无法知晓文件总大小的问题

问题:

     服务器端Java程序嵌入一个Apache ftpserver,客户端拟推广使用FileZilla FTP Client作为上传工具。

 程序在 FTP断点续传彻底完成之后对文件进行处理,但是无法确认文件在何时才最终被用户上传完,诸如网络断开、机器死机还是用户手动终止上传等问题造成的FTP上传对于中断服务器端程序来说也没法很好检测到。已确定文件传输使用FTP协议,但是在FTP协议中没有找到对于文件是否彻底上传完毕的命令,在抓包过程中也没有找到对于文件大小的控制符。

解决办法:

    1.据搜索得到网友提出的方法是由用户每次断点续传彻底完成之后将已经上传的文件改名,考虑了一下,该方法服务器端程序不易直接控制该过程,需要用户手动处理也不太现实。(NO)

   2.修改FileZilla FTP Client客户端源码编译,使每次断点上传过程中向服务器端报告所要上传文件的大小,服务器端则每次用户断点续传完之后检查该已上传文件的大小跟客户端报告的大小比较一下,如果等同则确定该文件已经上传完。(YES)

细节部分:

修改FileZilla FTP Client源码,在每次上传过程前的报告文件名部分将文件名后追加一个点分隔符和文件大小,另外为了客户端能正常地呈现服务器文件的文件名,将每次获取文件列表的文件名经过筛选,如果是以点分隔符和数字结尾的文件名,则将之去掉。

修改服务器端Apache ftpserver嵌入部分,在文件续传结束的监听部分实现对文件名解析得到客户端报告的文件总大小,然后和该文件的具体大小比较,如果等同则确定文件上传完毕,可以调用其它程序处理该文件了。

源码:

     src/engine/ftpcontrolsocket.cpp
	添加第2802行:
		cmd += "." + wxLongLong(pData->localFileSize).ToString();
     src/engine/directorylistingparser.cpp
	添加第8行:
		#include <wx/regex.h>
	添加第772行:
		wxString exp = _T(".+\\.[0-9]+$");
		wxRegEx regex;
		regex.Compile(exp);

		wxString r_exp = _T("\\.[0-9]+$");
		wxRegEx r_regex;
		r_regex.Compile(r_exp);
	后添加第892行:
		if (regex.Matches(entry.name))
		{
	  	wxString fileName=entry.name;
	  	m_pControlSocket->LogMessage(MessageType::Status, _("--r file:"+entry.name));
	  	r_regex.ReplaceFirst(&fileName,_T(""));
	 	entry.name=fileName;
		}
	FTP服务启动类中:
                FtpServerFactory serverFactory = new FtpServerFactory();
                serverFactory.setUserManager(um);
                serverFactory.getFtplets().put("upload", ftplet);
                ListenerFactory factory = new ListenerFactory();
                factory.setPort(port);
                Listener listener=factory.createListener();
                serverFactory.addListener("default", listener);
                FtpServer server = serverFactory.createServer();  
                server.start();
        ftplet监听器中onUploadEnd方法下:
                if(filename.matches(".+\\.\\d+$")){
			int lastDotIndex=uploadFile.getName().lastIndexOf(".");
			String suffix=uploadFile.getName().substring(lastDotIndex+1);
			Long declareFileSize=Long.parseLong(suffix);
			Long fileSize=uploadFile.getSize();
			if(fileSize<declareFileSize) return;
			else{
                             fileName=fileName.substring(0, lastDotIndex);
                             uploadFile.move(session.getFileSystemView().getFile(fileName));
                        }
                  }

编译:

   1)按照https://wiki.filezilla-project.org/Compiling_FileZilla_3_under_Windows说明进行编译,最后使用NSIS对已经编译完的可执行程序打成的安装包在安装过程中会报libgcc_s_dw2-1.dll缺失和libstdc++-6.dll调用错误问题,请到mingw目录下找到这两个同名文件复制/替换过来。

   2)java部分(省略)

总结:

 1.按照说明编译过程中一定要编译说明来进行编译,比如mingw的版本一定要相同,否则在编译过程中会出现问题。

 2.对于文件名的追加文件大小的策略是按照最简单、最小化修改的原则来考虑的,对于上传的文件名不能是以点加数字结尾是比较局限的,不过可以修改该策略,比如点加数字再加.tmp结尾等。

 3.对于本文提出的方案如果有其它需求,比如客户端上传对于文件大小、文件格式有要求的也可以借此发挥在客户端开始上传之前验证一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果您手动取消 FTP 文件输(例如,通过输或关闭 FTP 客户),那么输将停止,您需要重新开始输。如果您希望启用 FTP 断点功能,需要使用支持该功能的 FTP 客户服务器,并且需要在客户启用该功能。在这种情况下,如果输被断,您可以重新连接到服务器并从上次断的位置恢复输。 ### 回答2: FTP文件输协议)是一种用于在网络上进行文件输的标准协议。它允许用户通过将文件从一个计算机输到另一个计算机来进行文件共享。 对于FTP断点功能,当手动取消输时,过程断,剩余的文件将不会继输。这是因为断点是基于文件输的字节流来进行的,当输时,输进度和输位置将会丢失。 然而,如果使用支持断点FTP客户工具(如FileZilla等),可以通过在设置启用“断点”选项来实现断点功能。在这种情况下,如果过程手动取消了输,下一次重新启动输时,工具将会检测到已经输的部分文件,并从断点位置继输。 需要注意的是,FTP服务器必须支持并启用断点功能才能实现这种功能。因此,无论是FTP服务器还是客户工具,都需要适当配置和设置以确保断点功能的正常运行。 总之,当手动取消FTP文件输时,如果没有启用断点服务器不支持该功能,输将止并需要重新开始。但如果启用了该功能,并且服务器支持断点输将会从上一次的断点位置继输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值