FTP上传文件0字节问题,ftp上传文件字节


       这几天在做一个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;
	}
}


相关内容