一 FTP与HTTP
HTTP是超文本传输协议;面向网页的。
FTP是File Transfer Protocol,文件传输协议;面向文件的。
1.FTP
(1)FTP比HTTP复杂
FTP和HTTP一样都是Internet上广泛使用的协议,用来在两台计算机之间互相传送文件。相比于HTTP,FTP协议要复杂得多。
复杂的原因,是因为FTP协议要用到两个TCP连接,一个是命令链路,用来在FTP客户端与服务器之间传递命令;另一个是数据链路,用来上传或下载数据。
(2)FTP协议有两种工作方式:主动式和被动式。两种工作模式是服务端决定的
PORT(主动)方式的连接过程:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路。
当需要传送数据时, 客户端在命令链上发送PORT命令告诉 服务器:“我打开了XXXX端口,你过来连接我”。于是 服务器从20端口向客户端的XXXX端口发送连接请求,建立一条数据链路来传送数据。
PASV(被动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路。当需要传送数据时, 服务器在命令链上用PASV命令告诉 客户端:“我打开了XXXX端口,你过来连接我”。于是 客户端向服务器的XXXX端口发送连接请求,建立一条数据链路来传送数据。
从上面可以看出,两种方式的命令链路连接方法是一样的,而数据链路的建立方法就完全不同。而FTP的复杂性就在于此。
http与ftp的区别:
1.FTP要比HTTP早出现10年左右。
2.HTTP协议是用来浏览网站的,
3.FTP控制命令和传输数据使用两个不同的tcp,HTTP命令和数据传输都是一个tcp
4.HTTP持久连接,FTP每次有数据的需要时都创建一个新的连接。
5.HTTP中提供压缩算法,gzip比较有名
6.HTTP支持代理
————————————————
版权声明:本文此声明以上部分为CSDN博主「Diligent_wu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Diligent_wu/article/details/123458009
二 使用详情
第一步 创建服务端
1.下载安装Serv-U(免费试用30天)
2.下载破解包(花生壳)
请参考Serv-U 15.1.2安装使用_超凡脫俗的博客-CSDN博客_server u使用教程
第二步 在AS上编写客户端程序
FTP工具类
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTP;
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 android.R.string;
import android.graphics.Bitmap.Config;
import android.nfc.Tag;
import android.util.Log;
/*
* 用于Android和FTP服务器进行交互的工具类
*/
public class FTPUtils {
private static final String Tag = null;
private FTPClient ftpClient = null;
private static FTPUtils ftpUtilsInstance = null;
private String FTPUrl;
private int FTPPort;
private String UserName;
private String UserPassword;
private FTPUtils() {
ftpClient = new FTPClient();
}
/* 得到类对象实例 */
public static FTPUtils getInstance() {
if (ftpUtilsInstance == null) {
ftpUtilsInstance = new FTPUtils();
ftpUtilsInstance = new FTPUtils();
}
return ftpUtilsInstance;
}
/*
* 设置FTP服务器
* @param FTPUrl FTP服务器IP地址
* @param FTPPort FTP服务器端口号
* @param UserName 登陆FTP服务器的账号
* @param UserPassword 登陆FTP服务器的密码
*/
public boolean initFTPSetting(String FTPUrl,int FTPPort,String UserName,String UserPassword) {
this.FTPUrl = FTPUrl;
this.FTPPort= FTPPort;
this.UserName=UserName;
this.UserPassword=UserPassword;
int reply;
try {
//1.要连接的FTP服务器的地址、端口
ftpClient.connect(FTPUrl,FTPPort);
//2.登陆FTP服务器
ftpClient.login(UserName, UserPassword);
//3.看返回值是不是230,如果是,表示登陆成功
reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
//断开连接
ftpClient.disconnect();
return false;
}
return true;
} catch (SocketException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/*
* 上传文件
* @param FilePath 要上传文件所在的SDCard的路径
* @param FileName 要上传文件的文件名(如:SIM的唯一标识码)
* @return true为成功, false为失败
*/
// public boolean uploadFile(String FilePath,String FileName) {
// //判断FTP是否仍在连接
// if (!ftpClient.isConnected()) {
// if (!initFTPSetting(FTPUrl, FTPPort, UserName, UserPassword)) {
// return false;
// }
// }
//
// try {
// //1.设置存储路径
// ftpClient.makeDirectory("/ftpdata");
// ftpClient.changeWorkingDirectory("/ftpdata");
//
// //2.设置上传文件需要的一些基本信息
// ftpClient.setBufferSize(1024);
// ftpClient.setControlEncoding("UTF-8");
// ftpClient.enterLocalPassiveMode();
// ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
//
// //3.文件上传
// FileInputStream fileInputStream = new FileInputStream(FilePath);
// ftpClient.storeFile(FileName, fileInputStream);
//
// //4.关闭文件流
// fileInputStream.close();
//
// //5.退出登录FTP,关闭ftpClient连接
// ftpClient.logout();
// ftpClient.disconnect();
//
// } catch (IOException e) {
// Log.d(Tag, "UpLoad failed"); //输出错误消息
// e.printStackTrace();
// return false;
// }
// return false;
// }
/*
* 下载文件
* @param FilePath 要存放的文件路径
* @param FileName 远程FTP服务器上的那个文件的名字
* @return true为成功, false为失败
*/
public boolean downLoadFile(String FilePath,String FileName) {
//判断FTP是否仍在连接
if (!ftpClient.isConnected()) {
if (!initFTPSetting(FTPUrl, FTPPort, UserName, UserPassword)) {
return false;
}
}
try {
//1.转到指定的下载目录,如果是文件中的文件可以采用此方法
// ftpClient.changeWorkingDirectory("/ftpdata");
//2.列出该目录下的所有文件
FTPFile[] files = ftpClient.listFiles();
//3.遍历所有文件,找到指定的文件
for (FTPFile file : files) {
//String fileName = file.getName();
if (file.getName().equals(FileName)) {
//根据绝对路径初始化文件
File localFile = new File(FilePath);
//输出流
FileOutputStream outputStream = new FileOutputStream(localFile);
//下载文件
ftpClient.retrieveFile(file.getName(), outputStream);
//关闭流
outputStream.close();
}
}
//4.退出登录FTP,关闭ftpClient的连接
ftpClient.logout();
ftpClient.disconnect();
} catch (IOException e) {
// TODO: handle exception
Log.d(Tag, "DownLoad failed");
e.printStackTrace();
return false;
}
return true;
}
}
主活动
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
//buttons
private Button buttonDownLoad=null;
//FTP工具类
private FTPUtils ftpUtils = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取控件对象
buttonDownLoad=(Button)findViewById(R.id.button_2);
//设置控件相应函数
buttonDownLoad.setOnClickListener(this);
//搭建环境的API Level必须大于等于9
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
//初始化和FTP服务器交互的类
InitFTPServerSetting();
}
public void InitFTPServerSetting() {
ftpUtils = FTPUtils.getInstance();
boolean flag = ftpUtils.initFTPSetting("192.134.91.121", 21, "账号", "密码");
if (flag == true)
Toast.makeText(this, "连接成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_2:{
//下载文件
//参数为:要存放的文件路径和远程FTP文件名字
ftpUtils.downLoadFile("/data/data/com.example.ftptestapplication/files/down01", "request.txt");
}break;
default:
break;
}
}
}