1.yum安裝FTP服務
yum install vsftpd
2.啓動服務
cetoos 7 操作爲 /bin/systemctl restart vsftpd.service
centoos 6 操作爲 service vsftpd restart
3.設置開機啓動
chkconfig --level 35 vsftpd on
4.添加用戶
useradd ftpadmin -s /sbin/nologin
5.設置密碼
passwd ftpadmin (之後輸入兩次密碼)
java 代碼上傳連接
pom文件
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
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.*;
/**
* FTP工具類
*/
public class FTPUtil {
public static void main(String[] args) {
if (args.length == 0) {
args = new String[2];
args[0] = "D:\\docker.tar";
args[1] = "/mini3.tar";
}
FTPClient conn = null;
try {
conn = FTPUtil.getClient("yc3", 21, "ftpadmin", "123456");
for (int i = 0; i < 100; i++) {
Status status = FTPUtil.uploadController(conn, args[0], args[1] + i, 2000000);
System.out.println(status.getMessage());
}
} catch (Exception e) {
System.out.println("連接FTP出錯:" + e.getMessage());
} finally {
close(conn);
}
}
/**
* 狀態提示
*/
public enum Status {
Create_Directory_Fail("遠程服務器相應目錄創建失敗"),
Create_Directory_Success("遠程服務器闖將目錄成功"),
Upload_New_File_Success("上傳新文件成功"),
Upload_New_File_Failed("上傳新文件失敗"),
File_Exits("文件已經存在"),
Remote_Bigger_Local("遠程文件大於本地文件"),
Upload_From_Break_Success("斷點續傳成功"),
Upload_From_Break_Failed("斷點續傳失敗"),
Delete_Remote_Faild("刪除遠程文件失敗"),
Remote_File_Noexist("遠程文件不存在"),
Local_File_EXISTS("本地文件已經存在"),
Local_Bigger_Remote("本地文件大於遠程文件"),
Download_From_Break_Success("斷點下載文件成功"),
Download_From_Break_Failed("斷點下載文件失敗"),
Download_New_Success("全新下載文件成功"),
Download_New_Failed("全新下載文件失敗");
private String message;
Status(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
/**
* 獲取FTP服務器客戶端
*
* @param hostname 主機名
* @param port 端口
* @param username 用戶名
* @param password 密碼
* @return ftp客戶端
* @throws Exception
*/
public static FTPClient getClient(String hostname, int port, String username, String password) throws Exception {
FTPClient ftpClient = new FTPClient();
ftpClient.connect(hostname, port);
ftpClient.setControlEncoding("GBK");
if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
if (ftpClient.login(username, password)) {
return ftpClient;
}
}
throw new Exception();
}
/**
* 釋放資源
*
* @throws IOException
*/
public static void close(FTPClient ftpClient) {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void close(OutputStream out) {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void close(InputStream in) {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void close(RandomAccessFile raf) {
if (raf != null) {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 進度顯示方法
*
* @param isStart 是否是開始顯示進度
* @param process 當前進度偏移量
*/
private static void schedule(Boolean isStart, Long process) {
int sum = 50;//最大進度格子數,可修改
if (isStart) {
if (process == null) {
System.out.println();
return;
}
System.out.print("總量: ");
for (int i = 0; i < sum; i++) {
System.out.print("=");
}
System.out.println();
System.out.print("當前: ");
long span = 100 / sum;
if (process != 0) {
long current = process / span;
for (int i = 0; i < current; i++) {
System.out.print("=");
}
}
} else {
long span = 100 / sum;
if (process % span == 0) {
System.out.print("=");
}
}
}
/**
* 遞歸創建遠程服務器目錄
*
* @param remote 遠程服務器文件絕對路徑
* @param ftpClient FTPClient對象
* @return 目錄創建是否成功
* @throws IOException
*/
public static Status createDirecroty(String remote, FTPClient ftpClient) throws IOException {
Status status = Status.Create_Directory_Success;
String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"), "iso-8859-1"))) {
//如果遠程目錄不存在,則遞歸創建遠程服務器目錄
int end, start = 0;
if (directory.startsWith("/")) {
start = 1;
}
end = directory.indexOf("/", start);
while (true) {
String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1");
if (!ftpClient.changeWorkingDirectory(subDirectory)) {
if (ftpClient.makeDirectory(subDirectory)) {
ftpClient.changeWorkingDirectory(subDirectory);
} else {
return Status.Create_Directory_Fail;
}
}
start = end + 1;
end = directory.indexOf("/", start);
//檢查所有目錄是否創建完畢
if (end <= start) {
break;
}
}
}
return status;
}
/**
* 上傳文件到服務器,新上傳和斷點續傳
*
* @param ftpClient FTPClient引用
* @param remoteFile 遠程文件名,在上傳之前已經將服務器工作目錄做了改變
* @param localFile 本地文件File句柄,絕對路徑
* @param remoteSize 文件偏移量
* @param buffer 上傳文件buffer大小
* @return
* @throws IOException
*/
public static Status uploadFile(FTPClient ftpClient, String remoteFile, File localFile, long remoteSize, int buffer) throws IOException {
long startTime = System.currentTimeMillis();//起始時間
Status status;
long sum = localFile.length();//文件大小
long step = localFile.length() / 100;//進度百分數計算跨度
long process = 0; //當前進度百分比
long localreadbytes = 0L;
RandomAccessFile raf = new RandomAccessFile(localFile, "r");
OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"), "iso-8859-1"));
//斷點續傳
if (remoteSize > 0) {
ftpClient.setRestartOffset(remoteSize);
process = remoteSize / step;
raf.seek(remoteSize);
localreadbytes = remoteSize;
}
byte[] bytes = new byte[buffer];
schedule(true, process);//顯示初始進度與最大進度
int c;
while ((c = raf.read(bytes)) != -1) {
out.write(bytes, 0, c);
localreadbytes += c;
if (localreadbytes / step != process) {
process = localreadbytes / step;
schedule(false, process);//打印進度
}
}
schedule(true, null);//換行
close(out);
close(raf);
boolean result = ftpClient.completePendingCommand();
if (remoteSize > 0) {
status = result ? Status.Upload_From_Break_Success : Status.Upload_From_Break_Failed;
} else {
status = result ? Status.Upload_New_File_Success : Status.Upload_New_File_Failed;
}
//計算還需要傳輸的文件大小
long remaining = sum - remoteSize;
long endTime = System.currentTimeMillis();//結束時間
calculationSpeed(remaining, (endTime - startTime));
return status;
}
/**
* @param remaining 傳輸大小,b
* @param processingTime 處理時間,毫秒
*/
private static void calculationSpeed(long remaining, long processingTime) {
double scends = processingTime / 1000.0;//秒
double v = remaining / scends;
String unit[] = new String[]{"b", "k", "M", "G", "T", "P"};
int i = 0;
while (v > 1 << 10) {//v < 1024
i++;
v = v / 1024.0;
}
System.out.println(String.format("%.2f %s/s", v, unit[i]));
System.out.println("傳輸時間:" + scends + " s");
System.out.println("文件大小:" + remaining + " b");
}
/**
* 上傳文件控制端
*
* @param ftpClient ftp客戶端對象
* @param local 本地文件名稱,絕對路徑
* @param remote 遠程文件路徑,支持遞歸創建不存在的目錄結構
* @param buffer 上傳文件buffer緩存大小
* @return 上傳結果
* @throws IOException
*/
public static Status uploadController(FTPClient ftpClient, String local, String remote, int buffer) throws IOException {
//設置PassiveMode傳輸
ftpClient.enterLocalPassiveMode();
//設置以二進制流的方式傳輸
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.setControlEncoding("GBK");
Status result;
//對遠程目錄的處理
String remoteFileName = remote;
if (remote.contains("/")) {
remoteFileName = remote.substring(remote.lastIndexOf("/") + 1);
//創建服務器遠程目錄結構,創建失敗直接返回
if (createDirecroty(remote, ftpClient) == Status.Create_Directory_Fail) {
return Status.Create_Directory_Fail;
}
}
//檢查遠程是否存在文件
FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"), "iso-8859-1"));
if (files.length == 1) {
long remoteSize = files[0].getSize();
File f = new File(local);
long localSize = f.length();
if (remoteSize == localSize) {
return Status.File_Exits;
} else if (remoteSize > localSize) {
return Status.Remote_Bigger_Local;
}
//嘗試移動文件內讀取指針,實現斷點續傳
result = uploadFile(ftpClient, remoteFileName, f, remoteSize, buffer);
//如果斷點續傳沒有成功,則刪除服務器上文件,重新上傳
if (result == Status.Upload_From_Break_Failed) {
if (!ftpClient.deleteFile(remoteFileName)) {//刪除文件
return Status.Delete_Remote_Faild;
}
//重新下載
result = uploadFile(ftpClient, remoteFileName, f, 0, buffer);
}
} else {
result = uploadFile(ftpClient, remoteFileName, new File(local), 0, buffer);
}
return result;
}
/**
* 從FTP服務器上下載文件,支持斷點續傳,上傳百分比彙報
*
* @param ftpClient ftp客戶端
* @param remote 遠程文件路徑
* @param local 本地文件路徑
* @param buffer 下載文件緩存大小
* @return 上傳的狀態
* @throws IOException
*/
public static Status download(FTPClient ftpClient, String remote, String local, int buffer) throws Exception {
long startTime = System.currentTimeMillis();//起始時間
ftpClient.enterLocalPassiveMode();//設置被動模式
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//設置以二進制方式傳輸
//檢查遠程文件是否存在
FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"), "iso-8859-1"));
if (files.length == 0) {
return Status.Remote_File_Noexist;
}
long lRemoteSize = files[0].getSize();
File f = new File(local);
Status result;
long localTemp = 0L;
//本地存在文件,進行斷點下載
if (f.exists()) {
long localSize = f.length();
localTemp = localSize;
//判斷本地文件大小是否大於遠程文件大小
if (localSize > lRemoteSize) {//本地文件與服務器文件大小不同
return Status.Local_Bigger_Remote;
} else if (localSize == lRemoteSize) {//本地文件已經存在
return Status.Local_File_EXISTS;
}
//進行斷點續傳,並記錄狀態
FileOutputStream out = new FileOutputStream(f, true);
ftpClient.setRestartOffset(localSize);
InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"), "iso-8859-1"));
byte[] bytes = new byte[buffer];
long step = lRemoteSize / 100;
long process = localSize / step;
int c;
schedule(true, process);
while ((c = in.read(bytes)) != -1) {
out.write(bytes, 0, c);
localSize += c;
long nowProcess = localSize / step;
if (nowProcess > process) {
process = nowProcess;
schedule(false, process);
}
}
schedule(true, null);
in.close();
out.close();
boolean isDo = ftpClient.completePendingCommand();
if (isDo) {
result = Status.Download_From_Break_Success;
} else {
result = Status.Download_From_Break_Failed;
}
} else {
OutputStream out = new FileOutputStream(f);
InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"), "iso-8859-1"));
byte[] bytes = new byte[buffer];
long step = lRemoteSize / 100;
long process = 0;
schedule(true, process);
long localSize = 0L;
int c;
while ((c = in.read(bytes)) != -1) {
out.write(bytes, 0, c);
localSize += c;
long nowProcess = localSize / step;
if (nowProcess > process) {
process = nowProcess;
schedule(false, process);
}
}
schedule(true, null);
close(in);
close(out);
boolean upNewStatus = ftpClient.completePendingCommand();
if (upNewStatus) {
result = Status.Download_New_Success;
} else {
result = Status.Download_New_Failed;
}
}
long remaining = lRemoteSize - localTemp;
long endTime = System.currentTimeMillis();//結束時間
calculationSpeed(remaining, (endTime - startTime));
return result;
}
}