FTP上传文件0字节问题

原创 2017年03月31日 15:55:58

       这几天在做一个FTP上传文件的功能,在本地运行完全没有问题,上传文件成功。在公网(centos系统)上进行测试的时候就出了问题了,上传一直卡到storeFile上,一般是会卡住30-60秒,然后返回“false”,不报异常。所以我又开始怀疑代码的问题,在本地建了个CentOS的虚拟机,安装vsftp,结果是成功的。使用FTP上传工具进行处理,公网上传下载一点问题都没有,不会出现0字节的问题,至此,我就十分无耐了,同样的代码,在不同环境上支行的效果居然不一样。

       没办法,我只能想常规的想法一样,开始怀疑环境问题,按照说明,对公网的vsftp重新整了一遍,结果还是一样的,我去,什么鬼。

      在百度搜到了千千万万的处理方法,一个的试,都没有处理好。其中有一个文章说到FTP的模式,VSFTP有两种模式:pasv模式与port模式,什么意思,不懂,再搜索一下。

Port模式:
当客户端C向服务端S连接后,使用的是Port模式,那么客户端C会发送一条命令告诉服务端S(客户端C在本地打开了一个端口N在等着你进行数据连接),当服务端S收到这个Port命令后 就会向客户端打开的那个端口N进行连接,这种数据连接就生成了。
Pasv模式:
当客户端C向服务端S连接后,服务端S会发信息给客户端C,这个信息是(服务端S在本地打开了一个端口M,你现在去连接我吧),当客户端C收到这个信息后,就可以向服务端S的M端口进行连接,连接成功后,数据连接也建立了。
从上面的解释中,大家可以看到两种模式主要的不同是数据连接建立的不同,对于Port模式,是客户端C在本地打开一个端口等服务端S去连接建立数据连接;而Pasv模式就是服务端S打开一个端口等待客户端C去建立一个数据连接。

默认情况下,FTPCLIENT用的是port模式,可以在FTPCLIENT原码中看到

private void __initDefaults(){
this.__dataConnectionMode = 0;
....
}
public void enterLocalActiveMode() {
    this.__dataConnectionMode = 0;
    this.__passiveHost = null;
    this.__passivePort = -1;
}

public void enterLocalPassiveMode() {
    this.__dataConnectionMode = 2;
    this.__passiveHost = null;
    this.__passivePort = -1;
}
不知道是不是这个问题,试一下吧,反正模式是客户端发起的,代码上加入ftpClient.enterLocalPassiveMode();

直接运行,成功。

附上ftp上传与下载代码:

import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTPClient;

import java.io.*;
import java.util.logging.Logger;



/**
 * 含义:ftp的上传下载处理对象
 */
public class FtpFileTransfer {
	private FTPClient ftpClient = null;//ftp客户端对象
	private static String hostname = null;//FTP主机名称
	private static Integer port = 0;	//FTP服务端口
	private static String userName = null;//FTP服务器登录用户名
	private static String passwd=null;//FTP服务器登录密码
	private final String SPAPRATE_TOEKN = "/";
	private Logger logger = Logger.getLogger(this.getClass().getName());

	/**
	 * 从配置文件中获取配置值
	 */
	public FtpFileTransfer(String hostname,int port,String userName,String passwd){
		this.hostname = hostname;
		this.port = port;
		this.userName = userName;
		this.passwd = passwd;
	}
    /**
     * 方法描述:上传文件
     * @param srcPath 源文件路径
     * @param ftpPath FTP端存放路径
     * @param targetName FTP端存放名称
     * @return 操作是否成功
     */
    public boolean uploadFile(String srcPath,String ftpPath, String targetName){
    	boolean ret = false;
    	File file = new File(srcPath);
    	ret = uploadFile(file, ftpPath, targetName);
    	return ret;
    }
    
    /**
     * 方法描述:上传文件
     * @param file 待上传的文件
     * @param ftpPath 目标文件路径
     * @param targetName 目标名称
     * @return
     */
    public boolean uploadFile(File file,String ftpPath,String targetName){
    	if(file == null){
    		logger.info("File is null");
    		return false;
    	}
       	try {
       		InputStream is = new FileInputStream(file);
			return uploadFileStream(is, ftpPath, targetName);
		} catch (FileNotFoundException e) {
			return false;
		}
    }
    /**
     * 方法描述:上传文件
     * @param is 源文件流
     * @param ftpPath 放置在服务器上的位置
     * @param targetName 放置在服务器上的名称
     * @return 操作是否成功
     */
    public boolean uploadFileStream(InputStream is,String ftpPath, String targetName){
    	boolean ret = false;
    	if(is == null){
    		logger.info("File is null");
    		return ret;
    	}
        ret = this.connect2Ftp();
        if(!ret){
        	logger.info("connect to ftp server failure");
        	this.disconnect2Ftp();
        	return ret;
        }
        try { 
            boolean mkdir = this.makeDir(ftpPath);
            if(ftpPath.startsWith(SPAPRATE_TOEKN)){
            	ftpPath = ftpPath.substring(ftpPath.indexOf(SPAPRATE_TOEKN)+SPAPRATE_TOEKN.length());
            }
            ret = ftpClient.changeWorkingDirectory(ftpPath);
            if(ret){
            	ftpClient.setBufferSize(1024); 
            	ftpClient.setControlEncoding("utf-8");
				ftpClient.enterLocalPassiveMode();
            	ret = ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 
            	if(ret){
            		ret = ftpClient.storeFile(targetName, is);
            	}
            }
        } catch (IOException e) {
			e.printStackTrace();
            throw new RuntimeException("FTP客户端出错!", e);
        } finally { 
            IOUtils.closeQuietly(is); 
            disconnect2Ftp();
        } 
        return ret;
    }
    
    
    /**
     * 方法描述:下载文件
     * @param remoteFileName FTP上的文件名称,含路径
     * @param localFilePath 取到文件到本地后文件的存放位置
     * @return 操作是否成功
     */
    public boolean downloadFile(String remoteFileName, String localFilePath){
    	boolean ret = false;
    	remoteFileName = remoteFileName.trim();
    	if(remoteFileName.startsWith(SPAPRATE_TOEKN)){
    		remoteFileName = remoteFileName.substring(remoteFileName.indexOf(SPAPRATE_TOEKN)
    			+SPAPRATE_TOEKN.length());
        }else if(remoteFileName.startsWith("\\")){
        	remoteFileName = remoteFileName.substring(remoteFileName.indexOf("\\")
        		+"\\".length());
        }
    	
    	String path = null;
    	if(!remoteFileName.contains("//")){
    		if(remoteFileName.contains("/")){
    			remoteFileName=remoteFileName.replace("/", "\\");
    		}
    	}
    	path = remoteFileName.substring(0,remoteFileName.lastIndexOf("\\"));
    	String fileName = remoteFileName.substring(path.length()+2);
        FileOutputStream fos = null; 
		try {
			ret = connect2Ftp();
			if(!ret){
				 disconnect2Ftp();
				 return ret;
			}
			ret = ftpClient.changeWorkingDirectory(path);
		    fos = new FileOutputStream(localFilePath); 
		    ftpClient.setBufferSize(1024); 
		    ftpClient.setControlEncoding("utf-8");
		    //设置文件类型(二进制) 
		    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 
		    ret = ftpClient.retrieveFile(fileName, fos); 
		} catch (IOException e) {
		    throw new RuntimeException("FTP客户端出错!", e);
		} finally {
		    IOUtils.closeQuietly(fos);
		    disconnect2Ftp();
		} 
    	return ret;
	}
    
    /**
     * 方法描述:删除FTP服务器上的文件
     * @param filePath 文件名称
     * @return 删除成功/失败
     */
    public boolean deleteFile(String filePath){
    	boolean ret = false;
    	if(filePath == null || filePath.isEmpty() || filePath.equals("")){
    		return false;
    	}
    	try {
    		connect2Ftp();
    		ftpClient.changeWorkingDirectory("\\");
   			ret = ftpClient.deleteFile(filePath);
		} catch (IOException e) {
		}finally{
			disconnect2Ftp();
		}
    	return ret;
    }
    
    /**
     * 方法描述:删除文件夹
     * @param dirPath 文件夹路径
     * @param force 是否强制删除
     * @return 是否删除成功
     */
    public boolean deleteDirs(String dirPath, boolean force){
    	boolean ret = false;
    	if(dirPath.startsWith(SPAPRATE_TOEKN)){
    		dirPath = dirPath.substring(dirPath.indexOf(SPAPRATE_TOEKN)+SPAPRATE_TOEKN.length());
        }
    	String path = dirPath;
    	try {
    		ret = ftpClient.changeWorkingDirectory(dirPath);
    		String[] names = ftpClient.listNames();
    		if(force){
    			for(String name:names){
    				if(dirPath.endsWith(SPAPRATE_TOEKN)){
    					ret = deleteFile(dirPath+name);
    				}else{
    					ret = deleteFile(dirPath+SPAPRATE_TOEKN+name);
    				}
    			}
    		}
    		ret = ftpClient.changeWorkingDirectory("//");
    		while(true){
    			ret = ftpClient.removeDirectory(path);
    			if(path.contains(SPAPRATE_TOEKN)){
    				path = path.substring(0, path.lastIndexOf(SPAPRATE_TOEKN));
    			}else{
    				break;
    			}
    		}
		} catch (Exception e) {
		}
    	return ret;
    }
    /**
     * 方法描述:连接到远端的FTP服务器
     * @return 是否连接成功
     */
    private boolean connect2Ftp(){
    	boolean ret = false;
    	ftpClient = new FTPClient();
    	try {
			ftpClient.connect(hostname, port);
			ret = ftpClient.login(userName, passwd);
			logger.info("Finished login the ftp server, result="+ret);
		} catch (Exception e) {
		}
    	return ret;
    }
    
    /**
     * 方法描述:断开ftp链接
     */
    private void disconnect2Ftp(){
    	if(ftpClient != null){
    		try {
				ftpClient.disconnect();
			} catch (IOException e) {
			}
    	}
    }
    
    /**
     * 方法描述:根据目录要求创建ftp端的文件夹路径
     * @param dir 文件夹路径,如:绝对路径,/ab/cde/ef/hg,相对路径, ab/cd
     * @return 是否创建成功
     * @throws IOException
     */
    private boolean makeDir(String dir) throws IOException{
    	boolean ret = false;
    	int i = 0;
    	if(dir != null && !dir.isEmpty()){
    		String[] dirs = null;
    		int len = 0;
    		if(dir.contains("//")){
    			dir = dir.replace("//", SPAPRATE_TOEKN);
    			i = 1;
    		}
    		if(dir.contains(SPAPRATE_TOEKN)){
    			dirs = dir.split(SPAPRATE_TOEKN);
    			len = dirs.length;
    			StringBuffer sb = new StringBuffer();
    			for(;i<len;i++){
    				sb.append(dirs[i]); 
    				sb.append(SPAPRATE_TOEKN);
    				ret = ftpClient.makeDirectory(sb.toString());
    			}
    		}else{
    			ret = ftpClient.makeDirectory(dir);
    		}
    	}
    	return ret;
    }
    
    public boolean isFileExist(String filePath) {
		connect2Ftp();
		boolean ret = false;
		try {
			String rt = ftpClient.getModificationTime(filePath);
			if (rt != null && !rt.isEmpty()) {
				ret = true;
			}
		} catch (IOException e) {
		} finally {
			disconnect2Ftp();
		}
		return ret;
	}
}


FTPClient上传文件大小为0

问题原因一、FTP文件目录空间达到上限 二、网络策略变更造成,被防火墙拦截解决方案FTP协议有两种工作方式:PORT方式和PASV方式,默认为PORT方式,修改为PASV方式,目前问题解决。需要进一...
  • weixin_36907025
  • weixin_36907025
  • 2017年08月18日 14:14
  • 575

ftp上传文件失败,大小始终为0

主机:win7 虚拟机:ubuntu14.04 ubuntu中安装vsftpd,配置writing_enable=yes以及其它配置。上传文件大小始终为0。原因:磁盘空间被占满,没有空间写入: ...
  • Mr0Yang
  • Mr0Yang
  • 2016年08月25日 15:09
  • 2515

解决FTPClient上传文件为空

JAVA使用FTPClient上传文件时总是为空,而使用FileZilla客户端时却不会。 后来查了下资料,FTP服务器有被动模式和主动模式。(具体查另外资料) 在JAVA中将FTPClient设...
  • a1214345386
  • a1214345386
  • 2017年06月13日 15:39
  • 1446

java FTPClient 文件上传内容为空

如果你在本地的 java 项目里面去用 FtpClient 上传文件,然后虽然文件上传上去了,但是文件里面没有内容,那么这说明你的机器防火墙设置有问题如下图  为了可以正常测试,你需要把下面红线...
  • tengdazhang770960436
  • tengdazhang770960436
  • 2015年01月29日 19:34
  • 5370

java FTPClient 上传文件 0kb 问题

1.设置传输格式为二进制:ftpClient.setFileType(FTP.BINARY_FILE_TYPE); 2.关本地防火墙试一下,如果可行的话设置下防火墙中与java运行环境相关的选项(许...
  • a1015439240
  • a1015439240
  • 2016年10月28日 13:34
  • 2070

关于java使用Ftpclient上传到FTP服务器文件损坏的问题解决

作为职场菜鸟和java初学者,前几天被一个问题困扰,想到也许有如我一般的新手也会遇到同样的问题,所以决定先写下来,不行当个笔记存着也是不错的嘛。 言归正传,之前使用Ftpclient上传文件时,TX...
  • baidu_24140913
  • baidu_24140913
  • 2017年03月12日 13:04
  • 1748

解决ftp_put()函数0字节问题

今天修改原有的图片上传程序,因为新增了一台图片服务器,需要将图片上传到web服务器上之后,在ftp到图片服务器,ftp程序很早前就写过,还是比较简单的,就是要注意一下服务是主动模式还是被动模式。 ...
  • adparking
  • adparking
  • 2012年09月08日 15:54
  • 2490

ftp可登录但是无法下载,上传问题解决

  • 2017年12月13日 16:21
  • 1KB
  • 下载

关于ftp中文本模式和二进制模式上传文件的区别

文本模式,设置为assic; 二进制模式,设置为binary。 研究这个的起因是因为从arm板传输jpg图片到ftp服务器,ftp服务器却打不开图片。后来经过搜索和求教,发现,是传输模式造成的。 ...
  • zy416548283
  • zy416548283
  • 2013年07月23日 22:22
  • 5559

解决FTPClient linux 下载文件小于实际文件,线程挂起等问题

FTPClient调用retrieveFileStream导致线程挂起(防火墙问题);下载文件小于实际文件问题解决 实际是因为FTP的两种传输模式:主动模式和被动模式的不同而导致的 FTP...
  • tengdazhang770960436
  • tengdazhang770960436
  • 2015年02月13日 14:47
  • 4897
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:FTP上传文件0字节问题
举报原因:
原因补充:

(最多只允许输入30个字)