一、背景
项目中可能经常会遇到需要文件上传到服务器上,需要的时候从服务器获取。结合之前的博客 阿里云服务器上搭载 FTP 站点 本篇博客记录:如何通过java 实现FTP文件上传下载和删除功能。虽然网上有很多教程,但是或多或少都会有些问题。看到本篇文章,也许会让你少踩坑哦~
二、开发环境
- IDEA 2017.3.5
- Maven 3.5
- JDK 1.8
三、步骤详情
3.1、通过Apache FTP工具类实现文件上传下载以及删除
pom.xml 文件中,添加对应依赖:
代码语言:javascript复制<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
代码中使用到单元测试,需添加依赖:
代码语言:javascript复制<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
3.2、直接上代码
创建一个 FtpUtil 类:
代码语言:javascript复制package com.xmlvhy.ftp;
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 org.junit.Assert;
import org.junit.Test;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Author: 小莫
* Date: 2019-03-15 10:53
* Description: ftp 文件上传下载删除工具类
*/
public class FtpUtil {
/**
* Description: 向FTP服务器上传文件
*
* @param url FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param path FTP服务器保存目录
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false
*/
public static Map<String, Object> uploadFile(String url, int port, String username, String password, String path, String filename, FileInputStream input) {
boolean success = false;
Map<String, Object> map = new HashMap<>();
String filepath = "";
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(url, port);//连接FTP服务器
//如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
ftp.login(username, password);//登录
reply = ftp.getReplyCode();
//判断reply的code是否正常,一般正常为2开头的code
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
map.put("status", success);
map.put("filepath", filepath);
return map;
}
boolean a = ftp.changeWorkingDirectory("/");
System.out.println("转换目录结果1:" a);
String basePath = "/";
path = "static/images/20190315";
if (path == null || path.equals("/")) {//如果输入的路径为空或者为根路径,则不转换操作目录
} else {//否则创建想要上传文件的目录,并且将操作目录转为新创建的目录
//如果目录不存在创建目录
String[] dirs = path.split("/");
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) continue;
tempPath = "/" dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
success = false;
} else {
boolean b = ftp.changeWorkingDirectory(tempPath);
System.out.println("转换目录结果2:" b);
}
}
}
//ftp.makeDirectory(path);
//boolean b = ftp.changeWorkingDirectory(path);
//System.out.println("转换目录结果2:" b);
}
//ftp上传文件是以文本形式传输的,所以多媒体文件会失真,需要转为二进制形式传输
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//转码后可以文件名可以为中文
ftp.storeFile(new String(filename.getBytes("GBK"), "iso-8859-1"), input);
input.close();
ftp.logout();
success = true;
filepath = "ftp://" url ":" port "/" path "/" filename;
map.put("status", success);
map.put("filepath", filepath);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (Exception ioe) {
}
}
}
return map;
}
/**
* Description: 从FTP服务器下载文件
*
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param remotePath FTP服务器上的相对路径
* @param fileName 要下载的文件名
* @param localPath 下载后保存到本地的路径
* @return
*/
public static boolean downloadFile(String host, int port, String username, String password, String remotePath,
String fileName, String localPath) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
File localFile = new File(localPath "/" ff.getName());
OutputStream is = new FileOutputStream(localFile);
ftp.retrieveFile(ff.getName(), is);
is.close();
}
}
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* Description: 从FTP服务器删除文件
*
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param remotePath FTP服务器上的相对路径
* @param fileName 要删除的文件名
* @return
*/
public static boolean deleteFile(String host, int port, String username, String password, String remotePath,
String fileName) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
ftp.deleteFile(fileName);
}
}
//退出登录
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
}
再创建一个FtpTest 类,对 FtpUtil 中的方法进行测试
代码语言:javascript复制package com.xmlvhy.ftp;
import org.junit.Assert;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* Author: 小莫
* Date: 2019-03-18 15:24
* Description: ftp 工具类测试
*/
public class TtpTest {
/**
*功能描述: 上传文件
* @Author 小莫
* @Date 15:26 2019/03/18
* @Param []
* @return void
*/
@Test
public void test1() {
try {
FileInputStream in = new FileInputStream(new File("F:/user.png"));
String filePath = new SimpleDateFormat("yyyyMMdd").format(new Date());
String fileName = "user.png";
Map<String, Object> map = FtpUtil.uploadFile("您的服务器域名", 21, "ftptest", "ftp账户密码", filePath, fileName, in);
System.out.println(map.get("status") "====>" map.get("filepath"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
*功能描述: 下载文件
* @Author 小莫
* @Date 15:26 2019/03/18
* @Param []
* @return void
*/
@Test
public void test2() {
boolean flag = FtpUtil.downloadFile("您的服务器域名", 21, "ftptest", "ftp账户密码", "/", "user.png", "E:/");
Assert.assertEquals(true, flag);
}
/**
*功能描述: 删除文件
* @Author 小莫
* @Date 15:26 2019/03/18
* @Param []
* @return void
*/
@Test
public void test3() {
boolean flag = FtpUtil.deleteFile("您的服务器域名", 21, "ftptest", "ftp账户密码", "static/images/20190315", "user.png");
Assert.assertEquals(true, flag);
}
}
测试类中参数的相关说明
- 文件上传测试模块:我是本地 F 盘中有 ‘user.png’ 文件,这里注意修改您的路径文件;
- 特别注意:ftp 登录进去默认是到您 ftp 服务器的根路径,这里 ftp服务器的根路径以及 remotePath 都是 "/" ,这个路径一定要对,要不然多层级目录上传文件时候, makeDirectory(...)这个方法一直返回false,上传失败,我也是卡在这。当时还各种怀疑 ftp 服务器的配置啊,目录权限啊是不是有问题,卡了蛮久~
备注:
- changeWorkingDirectory()方法,是用来切换目录的,如果切换目录成功则返回 true,反之返回 false
- makeDirectory() 方法,是用来创建目录,该方法注意:只能创建一次目录(如果有多层目录的,则需要通过一层一层的去创建);如果当前存在目录则返回 true,反之如果创建失败则返回 false ;
//ftp站点的根目录,也就是你ftp账户登录成功进入到的目录
String basePath = "/";
//文件所要上传的路径,这个目录根据自己设定
path = "static/images/20190315";
if (path == null || path.equals("/")) {//如果输入的路径为空或者为根路径,则不转换操作目录
} else {//否则创建想要上传文件的目录,并且将操作目录转为新创建的目录
//如果目录不存在创建目录
String[] dirs = path.split("/");
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) continue;
tempPath = "/" dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
success = false;
} else {
boolean b = ftp.changeWorkingDirectory(tempPath);
System.out.println("转换目录结果2:" b);
}
}
}
}
四、测试结果
4.1、运行 test1() 方法上传一个文件
可以看到,文件成功上传到设定的目录中去了。删除 和 下载功能类似,只是调用的方法不一样,这里便不再展示结果了~
本篇博客涉及的代码 获取源码
本文作者: AI码真香
本文标题: JAVA 实现 FTP 文件上传、下载和删除
本文网址: https://www.xmlvhy.com/article/67.html
版权说明: 自由转载-非商用-非衍生-保持署名 署名-非商业性使用4.0 国际 (CC BY-NC 4.0)