今天通过FTPClient上传文件时出现,虽然无错误出现但是上传到服务器端的文件大小为0。
如图:
之前的代码:
//FTP文件上传
public static boolean upload(String hostname, int port, String username, String password,
String targetPath, String fileName, InputStream inputStream) throws SocketException, IOException {
//实例化ftpClient
FTPClient ftpClient = new FTPClient();
//设置登陆超时时间,默认是20s
ftpClient.setDataTimeout(12000);
//1.连接服务器
ftpClient.connect(hostname, port);
//2.登录(指定用户名和密码)
boolean b = ftpClient.login(username, password);
if (!b) {
log.info("ftp登陸超時");
if (ftpClient.isConnected()) {
// 断开连接
ftpClient.disconnect();
}
}
log.info("ftp登陸成功");
// 设置字符编码
ftpClient.setControlEncoding("UTF-8");
//基本路径,一定存在
String[] pathArray = targetPath.split("/");
for (String path : pathArray) {
if (path.equals("")) {
continue;
}
//3.指定目录 返回布尔类型 true表示该目录存在
boolean dirExsists = ftpClient.changeWorkingDirectory(path);
//4.如果指定的目录不存在,则创建目录
if (!dirExsists) {
//此方式,每次,只能创建一级目录
boolean flag = ftpClient.makeDirectory(path);
if (!flag) {
System.out.println("文件目录创建失败!");
return false;
}
ftpClient.changeWorkingDirectory(path);
}
}
log.info("重新指定上传文件的路径:" + targetPath);
//重新指定上传文件的路径
// ftpClient.changeWorkingDirectory(targetPath);
//5.设置上传文件的方式
ftpClient.setBufferSize(1024 * 1024 * 10);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
/**
* 6.执行上传
* remote 上传服务后,文件的名称
* local 文件输入流
* 上传文件时,如果已经存在同名文件,会被覆盖
*/
boolean uploadFlag = false;
try {
uploadFlag = ftpClient.storeFile(fileName, inputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
ftpClient.logout();
ftpClient.disconnect();
}
if (uploadFlag) {
System.out.println("上传成功!");
return true;
}
return false;
}
打上断点debug,当运行到
uploadFlag = ftpClient.storeFile(fileName, inputStream);
就卡着不到,也不报错。
百度到很多都说要设置为被动模式,要加:
ftpClient.enterLocalPassiveMode();
但是我明明已经加了还是不行。
于是各种找方法,终于知道问题在哪里了,原来 ftpClient.enterLocalPassiveMode();加的地方不对,要加在建立连接和登录之间才可以。
现在的代码:
//FTP文件上传
public static boolean upload(String hostname, int port, String username, String password,
String targetPath, String fileName, InputStream inputStream) throws SocketException, IOException {
//实例化ftpClient
FTPClient ftpClient = new FTPClient();
//设置登陆超时时间,默认是20s
ftpClient.setDataTimeout(12000);
//1.连接服务器
ftpClient.connect(hostname, port);
ftpClient.enterLocalPassiveMode();
//2.登录(指定用户名和密码)
boolean b = ftpClient.login(username, password);
if (!b) {
log.info("ftp登陸超時");
if (ftpClient.isConnected()) {
// 断开连接
ftpClient.disconnect();
}
}
log.info("ftp登陸成功");
// 设置字符编码
ftpClient.setControlEncoding("UTF-8");
//基本路径,一定存在
String[] pathArray = targetPath.split("/");
for (String path : pathArray) {
if (path.equals("")) {
continue;
}
//3.指定目录 返回布尔类型 true表示该目录存在
boolean dirExsists = ftpClient.changeWorkingDirectory(path);
//4.如果指定的目录不存在,则创建目录
if (!dirExsists) {
//此方式,每次,只能创建一级目录
boolean flag = ftpClient.makeDirectory(path);
if (!flag) {
System.out.println("文件目录创建失败!");
return false;
}
ftpClient.changeWorkingDirectory(path);
}
}
log.info("重新指定上传文件的路径:" + targetPath);
//重新指定上传文件的路径
// ftpClient.changeWorkingDirectory(targetPath);
//5.设置上传文件的方式
ftpClient.setBufferSize(1024 * 1024 * 10);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
/**
* 6.执行上传
* remote 上传服务后,文件的名称
* local 文件输入流
* 上传文件时,如果已经存在同名文件,会被覆盖
*/
boolean uploadFlag = false;
try {
uploadFlag = ftpClient.storeFile(fileName, inputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
ftpClient.logout();
ftpClient.disconnect();
}
if (uploadFlag) {
System.out.println("上传成功!");
return true;
}
return false;
}
问题解决,记录一下爬坑的过程,顺便希望能帮到其他人。
顺便记录下ftp文件下载
/**
* 文件下载--FTP服务器
*/
@LogRecord(name = "文件下载--FTP服务器")
@GetMapping(value = "/v1/zdyl/downloadFile")
public ResultJson downloadFileFtp(HttpServletRequest request, HttpServletResponse response) throws Exception {
String url = request.getParameter("url");
if (url == null)
throw new RRException("url is Empty!");
URI uri = new URI(url);
log.info("url:" + url);
String path = uri.getPath();
log.info("path:" + path);
InputStream inputStream = UploadUtil.downloadFile(ftpConfig.getHost(), ftpConfig.getPort(), ftpConfig.getUsername(), ftpConfig.getPassword(), path);
log.info("fileName:" + path.substring(path.lastIndexOf("/") + 1));
response.setContentType("application/force-download");
response.addHeader("Content-disposition", "attachment;fileName=" + path.substring(path.lastIndexOf("/") + 1));
OutputStream os = response.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = inputStream.read(buf)) != -1) {
os.write(buf, 0, len);
}
return null;
}
/**
* 功能:根据文件名称,下载文件流
*
* @return
* @throws IOException
*/
public static InputStream downloadFile(String hostname, int port, String username, String password, String remoteFilePath)
throws IOException {
InputStream in = null;
FTPClient ftpClient = null;
try {
//实例化ftpClient
ftpClient = new FTPClient();
//设置登陆超时时间,默认是20s
ftpClient.setDataTimeout(12000);
//1.连接服务器
ftpClient.connect(hostname, port);
ftpClient.enterLocalPassiveMode();
//2.登录(指定用户名和密码)
boolean b = ftpClient.login(username, password);
if (!b) {
log.info("登陸超時");
if (ftpClient.isConnected()) {
// 断开连接
ftpClient.disconnect();
}
}
log.info("登陸成功");
// 设置字符编码
ftpClient.setControlEncoding("UTF-8");
// 设置传输二进制文件
ftpClient.setBufferSize(1024 * 1024 * 10);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
throw new RRException("failed to connect to the FTP Server:");
}
// ftp文件获取文件
in = ftpClient.retrieveFileStream(encodingPath(remoteFilePath));
} catch (FTPConnectionClosedException e) {
log.error("ftp连接被关闭!", e);
throw e;
} catch (Exception e) {
log.error("ERR : upload file " + remoteFilePath + " from ftp : failed!", e);
throw new RRException("ERR : upload file " + remoteFilePath + " from ftp : failed!");
} finally {
ftpClient.disconnect();
}
return in;
}
/**
* 编码文件路径
*/
private static String encodingPath(String path) throws UnsupportedEncodingException {
// FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码
return new String(path.replaceAll("//", "/").getBytes("GBK"), "iso-8859-1");
}