java中用FTPClient,执行到ftp.storeFile(fileName, inputFile);无反应

package com.aa.test;

import cn.hutool.core.util.StrUtil;
import com.nuctech.platform.tip.constant.TipConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Description  ftp操作工具类
 */
@Slf4j
public class FTPClientUtil {

    /**
     * Description: 从FTP服务器下载文件
     * @param url FTP服务器hostname
     * @param port FTP服务器端口
     * @param username FTP登录账号
     * @param password FTP登录密码
     * @param remotePath FTP服务器上的相对路径
     * @param fileName 要下载的文件名
     * @param localPath 下载后保存到本地的路径
	 * @param  menuName 使用menuname 来作为zip包的名称
     * @return
     */
    public static boolean downloadFile(String url, int port, String username, String password, List<String> remotePathes,
                                       List<String> fileName, String localPath,String menuName)
    {
        boolean success = false;
        FTPClient ftp = new FTPClient();
		String zipPath=TipConstant.WORK_DIR+menuName+TipConstant.WORK_DIR_FIX;
		ZipOutputStream zipOutputStream=null;
		FileInputStream fileInputStream=null;
		OutputStream is=null;
		try
        {
        	//创建zip包
			zipOutputStream= new ZipOutputStream(new FileOutputStream(zipPath));
            int reply;

            // 连接FTP服务器
            if (port > -1)
            {
                ftp.connect(url, port);
            }
            else
            {
                ftp.connect(url);
            }
            //登录
            ftp.login(username, password);
            // 设置连接超时时间,5000毫秒
            ftp.setConnectTimeout(5000);
            // 设置中文编码集,防止中文乱码
            ftp.setControlEncoding("UTF-8");
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                log.info("下载ftp文件时,未连接到FTP,用户名或密码错误");
                ftp.disconnect();
                return success;
            }else {
                log.info("下载ftp文件时,FTP连接成功");
            }
            for(String remotePath:remotePathes){
				remotePath = new String(remotePath.getBytes("GBK"),"iso-8859-1");
				ftp.changeWorkingDirectory(remotePath);//转移到FTP服务器目录
				FTPFile[] fs = ftp.listFiles();
				for (FTPFile ff : fs)
				{
					if (fileName.contains(ff.getName()))
					{
						File file = new File(localPath);
						if(!file.exists()){
							file.mkdirs();
						}
						File localFile = new File(localPath + "/" + ff.getName());
						//开始从ftp下载图片
						is = new FileOutputStream(localFile);
						ftp.retrieveFile(ff.getName(), is);
						is.close();
						//创建条目
						String name=menuName+File.separator+ff.getName();
						ZipEntry zipEntry = new ZipEntry(name);
						zipOutputStream.putNextEntry(zipEntry);
						//获取文件资源
						String absolutePath = localFile.getAbsolutePath();
						fileInputStream = new FileInputStream(absolutePath);
						//把文件写到zip包中
						byte[] bytes = new byte[1024];
						int read;
						while ((read = fileInputStream.read(bytes)) != -1) {
							zipOutputStream.write(bytes,0,read);
						}
						fileInputStream.close();
					}
				}
			}
            ftp.logout();
            success = true;
        }
        catch (IOException e)
        {
            log.error("从FTP服务器下载文件异常:", e);
        }
        finally
        {
            if (ftp.isConnected())
            {
                try
                {
					is.close();
                	fileInputStream.close();
					zipOutputStream.close();
                    ftp.disconnect();
                }
                catch (IOException e)
                {
                    log.error("下载文件后关闭连接异常:", e);
                }
            }
        }
        return success;
    }

    /**
     * Description: 向FTP服务器上传文件
     * @param url FTP服务器hostname
     * @param port FTP服务器端口,如果默认端口请写-1
     * @param username FTP登录账号
     * @param password FTP登录密码
     * @param path FTP服务器保存目录
     * @param filename 上传到FTP服务器上的文件名
     * @param input 输入流
     * @return 成功返回true,否则返回false
     */
    public static boolean uploadFile(String url, int port, String username, String password, String path,
                                     String filename, InputStream input)
    {
        boolean success = false;
        FTPClient ftp = new FTPClient();
        try
        {
            int reply;

            // 连接FTP服务器
            if (port > -1)
            {
                ftp.connect(url, port);
            }
            else
            {
                ftp.connect(url);
            }

            // 登录FTP
            ftp.login(username, password);
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply))
            {
                ftp.disconnect();
                return success;
            }
			//切换工作路径
			List<String> pathList = getPathList(path);
            for(int i=0;i<pathList.size();i++){
				String dir = new String(pathList.get(i).getBytes("GBK"),"iso-8859-1");
				if(!ftp.changeWorkingDirectory(dir)){
            		if(!ftp.makeDirectory(dir)){
            			log.error("创建文件夹失败");
            			throw new IOException("创建文件夹失败");
					}
					ftp.changeWorkingDirectory(dir);
				}
			}
			ftp.setFileType(FTP.BINARY_FILE_TYPE);
            ftp.storeFile(filename, input);
            input.close();
            ftp.logout();
            success = true;
        }
        catch (IOException e)
        {
            success = false;
            log.error("从FTP服务器上传文件异常", e);
        }
        finally
        {
            if (ftp.isConnected())
            {
                try
                {
                    ftp.disconnect();
                }
                catch (IOException e)
                {
                    log.error("上传文件后关闭连接异常", e);
                }
            }
        }
        return success;
    }
	/**
	 * Description: 向FTP服务器上传xml文件
	 * @param url FTP服务器hostname
	 * @param port FTP服务器端口,如果默认端口请写-1
	 * @param username FTP登录账号
	 * @param password FTP登录密码
	 * @param path FTP服务器保存目录
	 * @param filename 上传到FTP服务器上的文件名
	 * @param input 输入流
	 * @return 成功返回true,否则返回false
	 */
	public static boolean uploadXmlFile(String url, int port, String username, String password, String path,
									 String filename, InputStream input)
	{
		boolean success = false;
		FTPClient ftp = new FTPClient();
		try
		{
			int reply;

			// 连接FTP服务器
			if (port > -1)
			{
				ftp.connect(url, port);
			}
			else
			{
				ftp.connect(url);
			}

			// 登录FTP
			ftp.login(username, password);
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply))
			{
				ftp.disconnect();
				return success;
			}
			String dir = new String(path.getBytes("GBK"),"iso-8859-1");
			if(!ftp.changeWorkingDirectory(dir)){
				if(!ftp.makeDirectory(dir)){
					log.error("创建文件夹失败");
					throw new IOException("创建文件夹失败");
				}
				ftp.changeWorkingDirectory(dir);
			}
			ftp.setFileType(FTP.BINARY_FILE_TYPE);
			ftp.storeFile(filename, input);
			input.close();
			ftp.logout();
			success = true;
		}
		catch (IOException e)
		{
			success = false;
			log.error("从FTP服务器上传文件异常", e);
		}
		finally
		{
			if (ftp.isConnected())
			{
				try
				{
					ftp.disconnect();
				}
				catch (IOException e)
				{
					log.error("上传文件后关闭连接异常", e);
				}
			}
		}
		return success;
	}

    /**
     * <删除FTP上的文件>
     * <远程删除FTP服务器上的录音文件>
     * @param url FTP服务器IP地址
     * @param port FTP服务器端口
     * @param username FTP服务器登录名
     * @param password FTP服务器密码
     * @param remotePath 远程文件路径
     * @param fileName 待删除的文件名
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static boolean deleteFtpFile(String url, int port, String username, String password, String remotePath,
                                        String fileName)
    {
        boolean success = false;
        FTPClient ftp = new FTPClient();
        try
        {
            int reply;

            // 连接FTP服务器
            if (port > -1)
            {
                ftp.connect(url, port);
            }
            else
            {
                ftp.connect(url);
            }

            // 登录
            ftp.login(username, password);
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply))
            {
                ftp.disconnect();
                return success;
            }
            // 转移到FTP服务器目录
			//删除空的文件夹
			String path = remotePath.substring(0, remotePath.lastIndexOf(File.separator));
			remotePath = new String(remotePath.getBytes("GBK"),"iso-8859-1");
            fileName=new String(fileName.getBytes("GBK"),"iso-8859-1");
			if(StrUtil.isBlank(fileName)){
				success=ftp.deleteFile(remotePath);
			}else{
				ftp.changeWorkingDirectory(remotePath);
				//获取当前目录下所有得子文件名称,进行删除
				FTPFile[] ftpFiles = ftp.listFiles();
				for (FTPFile ftpFile : ftpFiles) {
					boolean  isDel=ftp.deleteFile(remotePath + File.separator + ftpFile.getName());
					if(!isDel){
						throw new IOException("删除子文件失败");
					}
				}
				FTPFile[] ftpFiles1 = ftp.listFiles();
				if(null!=ftpFiles1&&ftpFiles1.length!=0){

				}else{
					ftp.changeWorkingDirectory(path);
					ftp.removeDirectory(remotePath);
				}
				success=true;
			}
            ftp.logout();
        }
        catch (IOException e)
        {
            log.error("FTP服务器上删除文件异常", e);
            success = false;
        }
        finally
        {
            if (ftp.isConnected())
            {
                try
                {
                    ftp.disconnect();
                }
                catch (IOException e)
                {
                    log.error("FTP服务器上删除文件后关闭连接", e);
                }
            }
        }
        return success;
    }

	/**
	 * <删除FTP上的文件>
	 * <远程删除FTP服务器上的录音文件>
	 * @param url FTP服务器IP地址
	 * @param port FTP服务器端口
	 * @param username FTP服务器登录名
	 * @param password FTP服务器密码
	 * @param remotePath 远程文件路径
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
    public static boolean delDirPath(String url, int port, String username, String password, String remotePath
									 ) {
		boolean success = false;
		FTPClient ftp = new FTPClient();
		try
		{
			int reply;

			// 连接FTP服务器
			if (port > -1)
			{
				ftp.connect(url, port);
			}
			else
			{
				ftp.connect(url);
			}

			// 登录
			ftp.login(username, password);
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply))
			{
				ftp.disconnect();
				return success;
			}
			String path = remotePath.substring(0, remotePath.lastIndexOf(File.separator));
			remotePath=new String(remotePath.getBytes("GBK"),"iso-8859-1");
			ftp.changeWorkingDirectory(remotePath);
			FTPFile[] ftpFiles = ftp.listFiles();
			if(null!=ftpFiles&&ftpFiles.length!=0){

			}else{
				ftp.changeWorkingDirectory(path);
				ftp.removeDirectory(remotePath);
			}
			ftp.logout();
		}
		catch (IOException e)
		{
			log.error("FTP服务器上删除文件异常", e);
			success = false;
		}
		finally
		{
			if (ftp.isConnected())
			{
				try
				{
					ftp.disconnect();
				}
				catch (IOException e)
				{
					log.error("FTP服务器上删除文件后关闭连接", e);
				}
			}
		}
		return success;

	}


	/**
	 * <删除FTP上的文件>
	 * <远程删除FTP服务器上的录音文件>
	 * @param url FTP服务器IP地址
	 * @param port FTP服务器端口
	 * @param username FTP服务器登录名
	 * @param password FTP服务器密码
	 * @param remotePath 远程文件路径
	 * @param fileName 待删除的文件名
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public static boolean delXmlFile(String url, int port, String username, String password, String remotePath,
										String fileName)
	{
		boolean success = false;
		FTPClient ftp = new FTPClient();
		try
		{
			int reply;

			// 连接FTP服务器
			if (port > -1)
			{
				ftp.connect(url, port);
			}
			else
			{
				ftp.connect(url);
			}

			// 登录
			ftp.login(username, password);
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply))
			{
				ftp.disconnect();
				return success;
			}
			remotePath = new String(remotePath.getBytes("GBK"),"iso-8859-1");
			fileName=new String(fileName.getBytes("GBK"),"iso-8859-1");
			//切换工作目录
			ftp.changeWorkingDirectory(remotePath);
			//获取当前目录下所有得子文件名称,进行删除
			boolean  isDel=ftp.deleteFile(remotePath + File.separator + fileName);
			if(!isDel){
				throw new IOException("删除子文件失败");
			}
			success=true;
			ftp.logout();
		}
		catch (IOException e)
		{
			log.error("FTP服务器上删除文件异常", e);
			success = false;
		}
		finally
		{
			if (ftp.isConnected())
			{
				try
				{
					ftp.disconnect();
				}
				catch (IOException e)
				{
					log.error("FTP服务器上删除文件后关闭连接", e);
				}
			}
		}
		return success;
	}

	//分割路径
	public static List<String> getPathList(String path){
		String[] dirs = path.split("/");
		List<String> list = new ArrayList<>();
		String pathname = "";
		for(String str : dirs){
			if(StrUtil.isEmpty(str)){
				continue;
			}
			pathname = pathname + "/" + str;
			list.add(pathname);
		}
		return list;
	}



}

工具类,一找一大把,那就不多说了。我主要说说遇到的问题:连接ftp的客户端,我没有和ftp服务器部署在同一个电脑,如果是同一个电脑,应该也没啥问题。我发现,在我拿到流数据,往ftp文件夹下写图片数据的时候,没有把图片写进去。通过一行一行代码打印日志,排查发现

boolean storeFile = ftp.storeFile(filename, input);方法没有拿到返回值,没有反应。

原因是:

FTP协议有两种工作方式:PORT方式和PASV方式,中文意思为主动式和被动式。

PORT(主动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路。当需要传送数据时,客户端在命令链路上用PORT 命令告诉服务器:“我打开了XXXX端口,你过来连接我”。于是服务器从20端口向客户端的 XXXX端口发送连接请求,建立一条数据链路来传送数据。

PASV(被动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请 求,服务器接受连接,建立一条命令链路。当需要传送数据时,服务器在命令链路上用PASV 命令告诉客户端:“我打开了XXXX端口,你过来连接我”。于是客户端向服务器的XXXX端口 发送连接请求,建立一条数据链路来传送数据。

解决办法:ftpclient.enterLocalPassiveMode();

/**
	 * Description: 向FTP服务器上传文件
	 *
	 * @param url      FTP服务器hostname
	 * @param port     FTP服务器端口,如果默认端口请写-1
	 * @param username FTP登录账号
	 * @param password FTP登录密码
	 * @param path     FTP服务器保存目录
	 * @param filename 上传到FTP服务器上的文件名
	 * @param input    输入流
	 * @return 成功返回true,否则返回false
	 **/
	public static boolean uploadFile(String url, int port, String username, String password, String path,
									 String filename, InputStream input) {
		log.info("开始调用uploadfile方法");
		boolean success = false;
		FTPClient ftp = new FTPClient();
		try {
			int reply;

			// 连接FTP服务器
			if (port > -1) {
				log.info("开始调用uploadfile方法,url:"+url+",port:"+port);
				ftp.connect(url, port);
			} else {
				log.info("开始调用uploadfile方法else,url:"+url+",port:"+port);
				ftp.connect(url);
			}
			// 登录FTP
			boolean login = ftp.login(username, password);
			log.info("开始调用uploadfile方法,登录FTP,login:"+login);
			reply = ftp.getReplyCode();
			log.info("开始调用uploadfile方法,登录FTP,reply:"+reply);
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				log.info("开始调用uploadfile方法==ftp.disconnect()");
				return success;
			}
			String[] ftpPathDir = path.split("/");
			//切换工作路径
			List<String> pathList = Arrays.asList(ftpPathDir);
			for (int i = 0; i < pathList.size(); i++) {
				String dir = new String(pathList.get(i).getBytes("GBK"), "iso-8859-1");
				if (!ftp.changeWorkingDirectory(dir)) {
					if (!ftp.makeDirectory(dir)) {
						log.error("创建文件夹失败");
					}
					ftp.changeWorkingDirectory(dir);
				}
			}
			boolean setFileType = ftp.setFileType(FTP.BINARY_FILE_TYPE);
			log.info("开始调用uploadfile方法==setFileType:"+setFileType);
			ftp.enterLocalPassiveMode();
			boolean storeFile = ftp.storeFile(filename, input);
			log.info("开始调用uploadfile方法==storeFile:"+storeFile);
			input.close();
			boolean logout = ftp.logout();
			log.info("开始调用uploadfile方法==logout:"+logout);
			success = true;
		} catch (IOException e) {
			success = false;
			log.error("从FTP服务器上传文件异常", e);
		} finally {
			log.error("finally从FTP服务器上传文件异常");
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException e) {
					log.error("上传文件后关闭连接异常", e);
				}
			}
		}
		log.info("调用uploadfile方法结束,结果="+success);
		return success;
	}

### 回答1: ftpclient.storefileFTPClient类中的一个方法,用于将本地文件上传到FTP服务器上。 具体用法如下: 1. 首先创建一个FTPClient对象,并连接到FTP服务器。 2. 然后使用storefile方法上传文件,该方法需要传入两个参数:远程文件名和本地文件名。 3. 上传完成后,关闭FTP连接。 示例代码: ``` FTPClient ftpClient = new FTPClient(); ftpClient.connect("ftp.example.com"); ftpClient.login("username", "password"); File localFile = new File("localfile.txt"); InputStream inputStream = new FileInputStream(localFile); ftpClient.storeFile("remotefile.txt", inputStream); inputStream.close(); ftpClient.logout(); ftpClient.disconnect(); ``` 以上代码将本地文件localfile.txt上传到FTP服务器上,并将其命名为remotefile.txt。 ### 回答2: FTPClientJava中常用的FTP客户端连接工具,其中ftpclient.storefileFTPClient中上传文件的方法之一。 使用ftpclient.storefile进行上传文件,首先需要创建一个FTP连接,并使用FTPClient的login方法进行登录。然后,需要设置上传文件的相关参数,包括上传文件的路径、文件名、上传模式等。 在设置好相关参数之后,调用ftpclient.storefile方法即可上传文件到指定的FTP服务器中。上传文件的过程需要关注的是上传进度、异常处理和上传结果的返回值。FTPClient中提供了多种方法来获取上传进度、处理异常和获得上传结果。 需要注意的是,在上传文件的过程中,我们需要保证文件名和上传路径的正确性,避免出现上传路径不存在或文件名重复等问题。同时,也需要检查上传文件的访问权限,确保上传文件的可读性和可写性。 总之,ftpclient.storefile方法是Java中上传文件到FTP服务器的重要方法,使用时需要注意设置上传参数并处理相关异常,以确保文件能够正确地上传到FTP服务器中。 ### 回答3: FTPClientJava中常用的FTP客户端库,可以连接到FTP服务器执行各种FTP操作。其中,storefileFTPClient中用来上传文件的方法。 storefile的基本用法是将本地文件上传到FTP服务器中指定的路径下。使用该方法需要执行以下步骤: 1. 连接到FTP服务器。可以通过FTPClient的connect方法连接FTP服务器,需要指定服务器的主机地址、端口号、用户名和密码等信息。 2. 设置传输模式。FTPClient支持两种传输模式:二进制传输和ASCII传输。通过设置FTPClient的setFileType方法来指定传输模式,一般情况下使用二进制传输。 3. 设置工作目录。使用FTPClient的changeWorkingDirectory方法将FTP服务器的当前工作目录切换到要上传文件的目录。 4. 执行上传操作。调用FTPClientstoreFile方法上传文件。需要指定本地文件的路径和文件名,以及上传后保存在FTP服务器中的文件名。 5. 关闭连接。上传完成后,使用FTPClient的disconnect方法关闭与FTP服务器之间的连接。 以下是storefile方法的代码示例: ``` FTPClient ftpClient = new FTPClient(); ftpClient.connect("ftp.example.com", 21); ftpClient.login("username", "password"); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.changeWorkingDirectory("/upload"); File localFile = new File("localfile.txt"); InputStream inputStream = new FileInputStream(localFile); ftpClient.storeFile("uploadedfile.txt", inputStream); inputStream.close(); ftpClient.logout(); ftpClient.disconnect(); ``` 在实际使用中,还需要处理上传文件失败的情况,并且考虑到网络传输中可能出现的稳定性问题,需要进行断点续传等操作。对于大文件的上传,可以考虑使用多线程或分片上传等技术来提高上传效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值