抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

FTP服务器是什么意思?

FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务,FTP是File Transfer Protocol(文件传输协议),顾名思义,就是专门用来传输文件的协议,简单地说,支持FTP协议的服务器就是FTP服务器。

FTP是用来在两台计算机之间传输文件,是Internet中应用非常广泛的服务之一,它可根据实际需要设置各用户的使用权限,同时还具有跨平台的特性,即在UNIX、Linux和Windows等操作系统中都可实现FTP客户端和服务器,相互之间可跨平台进行文件的传输。因此,FTP服务是网络中经常采用的资源共享方式之一,FTP协议有PORT和PASV两种工作模式,即主动模式和被动模式。

FTP(File Transfer Protocol)即文件传输协议,是一种基于TCP的协议,采用客户/服务器模式,通过FTP协议,用户可以在FTP服务器中进行文件的上传或下载等操作,虽然现在通过HTTP协议下载的站点有很多,但是由于FTP协议可以很好地控制用户数量和宽带的分配,快速方便地上传、下载文件,因此FTP已成为网络中文件上传和下载的首选服务器,同时,它也是一个应用程序,用户可以通过它把自己的计算机与世界各地所有运行FTP协议的服务器相连,访问服务器上的大量程序和信息。

FTP服务的功能是实现完整文件的异地传输,特点如下:

(一)FTP使用两个平行连接:控制连接和数据连接。控制连接在两主机间传送控制命令,如用户身份、口令、改变目录命令等。数据连接只用于传送数据。

(二)在一个会话期间,FTP服务器必须维持用户状态,也就是说,和某一个用户的控制连接不能断开。另外,当用户在目录树中活动时,服务器必须追踪用户的当前目录,这样,FTP就限制了并发用户数量。

(三)FTP支持文件沿任意方向传输。当用户与一远程计算机建立连接后,用户可以获得一个远程文件也可以将一本地文件传输至远程机器。

Java上传文件至FTP服务器

FTP工具类


import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.function.Function;


/**
*
* @author 答案
*/
@Component
public class FtpHelper implements Closeable {
private final static Logger log = LoggerFactory.getLogger(FtpHelper.class);
private FTPClient ftp = null;
boolean _isLogin = false;
public static FtpHelper getInstance() {
return new FtpHelper();
}

/**
*
* ftp 匿名登录
* @param ip ftp服务地址
* @param port 端口号
*/
public boolean login(String ip,int port){
//如果没有设置ftp用户可将username设为anonymous,密码为任意字符串
return login(ip, port,"anonymous","");
}
/**
*
* ftp登录
* @param ip ftp服务地址
* @param port 端口号
* @param uname 用户名
* @param pass 密码
*/
public boolean login(String ip,int port, String uname, String pass) {
ftp = new FTPClient();
// boolean flag=false;
try {
// 连接
ftp.connect(ip,port);
_isLogin = ftp.login(uname, pass);
log.info(_isLogin?"登录成功":"登录失败");
// 检测连接是否成功
int reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
System.err.println("FTP服务器拒绝连接 ");
return false;
}
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
/**
* 上传后触发
*/
public Function<FtpFileInfo, Boolean> onUploadFileAfter;

/**
*
* ftp上传文件
* @param localFileName 待上传文件
* @param ftpDirName ftp 目录名
* @param ftpFileName ftp目标文件
* @return true||false
*/
public boolean uploadFile(String localFileName
,String ftpDirName
, String ftpFileName) {
return uploadFile(localFileName, ftpDirName, ftpFileName,false);
}
/**
*
* ftp上传文件
* @param localFileName 待上传文件
* @param ftpDirName ftp 目录名
* @param ftpFileName ftp目标文件
* @param deleteLocalFile 是否删除本地文件
* @return true||false
*/
public boolean uploadFile(String localFileName
, String ftpDirName
, String ftpFileName
, boolean deleteLocalFile) {

if(StringUtils.isEmpty(ftpFileName))
throw new RuntimeException("上传文件必须填写文件名!");

File srcFile = new File(localFileName);
if(!srcFile.exists())
throw new RuntimeException("文件不存在:"+localFileName);

try (FileInputStream fis = new FileInputStream(srcFile)) {
//上传文件
boolean flag = uploadFile(fis,ftpDirName,ftpFileName);
//上传前事件
if(onUploadFileAfter!=null){
onUploadFileAfter.apply(new FtpFileInfo(localFileName,ftpDirName,ftpFileName));
}
//删除文件
if(deleteLocalFile){
srcFile.delete();
log.info("ftp删除源文件:{0}",srcFile);
}
fis.close();
return flag;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
}
}


/**
*
* ftp上传文件 (使用inputstream)
* @param ftpDirName ftp 目录名
* @param ftpFileName ftp目标文件
* @return true||false
*/
public boolean uploadFile(FileInputStream uploadInputStream
,String ftpDirName
, String ftpFileName) {
if(StringUtils.isEmpty(ftpFileName))
throw new RuntimeException("上传文件必须填写文件名!");

try {
// 设置上传目录(没有则创建)
if(!createDir(ftpDirName)){
throw new RuntimeException("切入FTP目录失败:"+ftpDirName);
}
ftp.setBufferSize(1024);
//解决上传中文 txt 文件乱码
ftp.setControlEncoding("GBK");
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode("zh");


// 设置文件类型(二进制)
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
// 上传
String fileName = new String(ftpFileName.getBytes("GBK"),"iso-8859-1");
if(ftp.storeFile(fileName, uploadInputStream)){
uploadInputStream.close();
log.info("文件上传成功");
return true;
}

return false;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
}
}
/**
* 下载文件
* @param ftpDirName ftp目录名
* @param ftpFileName ftp文件名
* @param localFileFullName 本地文件名
* @return
* @author xxj
*/
public boolean downloadFile(String ftpDirName,
String ftpFileName, String localFileFullName) {
try {
if("".equals(ftpDirName))
ftpDirName="/";
String dir = new String(ftpDirName.getBytes("GBK"),"iso-8859-1");
if(!ftp.changeWorkingDirectory(dir)){
log.info("切换目录失败:"+ftpDirName);
return false;
}
FTPFile[] fs = ftp.listFiles();
String fileName = new String(ftpFileName.getBytes("GBK"),"iso-8859-1");
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
FileOutputStream is = new FileOutputStream(new File(localFileFullName));
ftp.retrieveFile(ff.getName(), is);
is.close();
log.info("下载ftp文件已下载:"+localFileFullName);
return true;
}
}
log.info("下载ftp文件失败:"+ftpFileName+";目录:"+ftpDirName);
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


/**
*
* 删除ftp上的文件
*
* @param ftpFileName
* @return true || false
*/
public boolean removeFile(String ftpFileName) {
boolean flag ;
try {
ftpFileName = new String(ftpFileName.getBytes("GBK"),"iso-8859-1");
flag = ftp.deleteFile(ftpFileName);
log.info(flag?"成功":"失败");
return flag;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/**
* 删除空目录
* @param dir
* @return
*/
public boolean removeDir(String dir){
if(StringUtil.startWith(dir, "/"))
dir="/"+dir;
try {
String d = new String(dir.toString().getBytes("GBK"),"iso-8859-1");
return ftp.removeDirectory(d);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 创建目录(有则切换目录,没有则创建目录)
* @param dir
* @return
*/
public boolean createDir(String dir){
if(StringUtils.isEmpty(dir))
return true;
String d;
try {
//目录编码,解决中文路径问题
d = new String(dir.toString().getBytes("GBK"),"iso-8859-1");
//尝试切入目录
if(ftp.changeWorkingDirectory(d))
return true;
dir = StringUtil.trimStart(dir, "/");
dir = StringUtil.trimEnd(dir, "/");
String[] arr = dir.split("/");
StringBuffer sbfDir=new StringBuffer();
//循环生成子目录
for(String s : arr){
sbfDir.append("/");
sbfDir.append(s);
//目录编码,解决中文路径问题
d = new String(sbfDir.toString().getBytes("GBK"),"iso-8859-1");
//尝试切入目录
if(ftp.changeWorkingDirectory(d))
continue;
if(!ftp.makeDirectory(d)){
log.info("[失败]ftp创建目录:"+sbfDir.toString());
return false;
}
log.info("[成功]创建ftp目录:"+sbfDir.toString());
}
//将目录切换至指定路径
return ftp.changeWorkingDirectory(d);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}



/**
*
* 销毁ftp连接
*
*/
private void closeFtpConnection() {
_isLogin = false;
if (ftp != null) {
if (ftp.isConnected()) {
try {
ftp.logout();
ftp.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


/**
*
* 销毁ftp连接
*
*/
@Override
public void close() {
this.closeFtpConnection();
}

public static class FtpFileInfo{
public FtpFileInfo(String srcFile,String ftpDirName,String ftpFileName){
this.ftpDirName=ftpDirName;
this.ftpFileName=ftpFileName;
this.srcFile=srcFile;
}
String srcFile;
String ftpDirName;
String ftpFileName;
String ftpFileFullName;

public String getSrcFile() {
return srcFile;
}
public void setSrcFile(String srcFile) {
this.srcFile = srcFile;
}
public String getFtpDirName() {
return ftpDirName;
}
public void setFtpDirName(String ftpDirName) {
this.ftpDirName = ftpDirName;
}
public String getFtpFileName() {
return ftpFileName;
}
public void setFtpFileName(String ftpFileName) {
this.ftpFileName = ftpFileName;
}
/**
* 获取ftp上传文件的完整路径名
* @return
* @author xxj
*/
public String getFtpFileFullName() {
return StringUtil.Combine("/",ftpDirName,ftpFileName);
}

}
}

工具类


public final class StringUtil {


/**
* 删除起始字符
* @param
* @return
* @author xxj 2017年4月27日
*/
public static String trimStart(String str,String trim){
if(str==null)
return null;
return str.replaceAll("^("+trim+")+", "");
}

/**
* 以字符开头
* @param s
* @return
* @author xxj 2017年4月27日
*/
public static boolean startWith(String str,String s){
return str.startsWith(s);
}

/**
* 删除末尾字符
* @param
* @return
* @author xxj 2017年4月27日
*/
public static String trimEnd(String str,String trim){
if(str==null)
return null;
return str.replaceAll("("+trim+")+$", "");
}

/**
* 去空格
*/
public static String trim(String str)
{
return (str == null ? "" : str.trim());
}

/**
* 合并路径
* @param args
* @return
* @author xxj 2017年4月27日
*/
public static String Combine(String ...args){
if(args==null || args.length==0)
return "";
StringBuffer sbf = new StringBuffer();
for(String s:args){
// //纯协议开头不处理,如:http://,d:/,linux首个/不处理
// if(s.matches("^[a-zA-z]+://$")){
// sbf.append(s);
// continue;
// }
//首位地址只删除尾部正反斜杠
if(sbf.length()==0){
sbf.append(s.replaceAll("/{1,}$|\\{1,}$", ""));
continue;
}

if(sbf.length()>0)
sbf.append("/");
//去除首尾正反斜杠
sbf.append(s
.replaceAll("^/{1,}|^\\{1,}", "")
.replaceAll("/{1,}$|\\{1,}$", ""));
}

return sbf.toString();
}

}







public static File transferToFile(MultipartFile file) throws Exception{
// 选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(file.getOriginalFilename());
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;

}

测试

@CrossOrigin
@PostMapping("/ftp/uploading")
public Map<String, Object> ftpImageByCover(MultipartFile file) throws Exception {

File transferToFile = FileUtil.transferToFile(file);

//登录ftp服务器,使用用户名 和密码
ftpHelper.login(host,21,username, password);//改成自己的
//上传文件
FileInputStream inputStream = new FileInputStream(transferToFile);

ftpHelper.uploadFile(inputStream,path,transferToFile.getName());

return this.getJsonMap();
}

免费的FTP软件

1、FileZilla (官网:https://www.filezilla.cn/)
2、WinSCP (官网:https://winscp.net/eng/docs/lang:chs)
3、XFTP(官网:https://www.xshell.com/zh/xftp/)

评论