目錄
我的需求:
1.安裝過程:
附帶圖:2.開啟遠端通路
3.修改配置檔案,禁止匿名通路
4.建立一個使用者
5.開啟被動模式
6.配置使用者ftp權限及通路路徑限制
碰見的問題:
整合nginx
我的需求:
1.搭建完ftp後,添加一個ftp使用者,隻允許對指定的目錄進行讀寫操作,其餘目錄禁止讀寫.
2.在java代碼中使用ftp使用者賬戶,進行上傳檔案/圖檔.
3.使用nginx整合ftp,提供對外通路檔案/圖檔的url路徑.
在java中使用ftp上傳時,有關于目錄的問題,參考這篇文章:https://blog.csdn.net/qq_23167527/article/details/66975727
1.安裝過程:
第一步:檢查是否安裝了vsftpd
rpm -qa | grep vsftpd
第二步:如果沒有安裝則安裝vsftpd
yum -y install vsftpd
第三步: 補充知識點,不需要全部執行
systemctl status vsftpd 檢視服務狀态
systemctl start vsftpd 啟動服務
systemctl stop vsftpd 暫停服務
systemctl restart vsftpd 重新開機啟動服務
systemctl enable vsftpd 開機自啟動
systemctl disable vsftpd 取消開機自啟動
附帶圖:
阿裡雲ECS,CentOs7.3搭建FTP伺服器,附帶java使用demo 2.開啟遠端通路

在阿裡雲安全組中,添加安全組規則
3.修改配置檔案,禁止匿名通路
編輯配置檔案
vim /etc/vsftpd/vsftpd.conf
預設是yes将其改為no
anonymous_enable=NO
4.建立一個使用者
建立一個使用者使用ftp
useradd ftpuser -d /home/ftpimage
設定使用者密碼,輸入兩次就行
passwd ftpuser
5.開啟被動模式
被動模式預設是開啟的,但是需要指定一個端口範圍.
vim /etc/vsftpd/vsftpd.conf
在最後面加上,注意這裡是開啟範圍端口,意思是說,8800~8899這個範圍内的端口必須全部開啟,當然你也可以自己随便設定
pasv_min_port=8800
pasv_max_port=8899
表示端口範圍為8800~8899,這個可以随便修改,改完記得重新開機一下vsftpd服務。
友情提示:最大和最小,最好設定為一樣,這樣就成了固定端口了
對應的我們也應該在安全組政策中添加這個範圍的端口。
6.配置使用者ftp權限及通路路徑限制
編輯配置檔案,在末尾添加,這三行
vim /etc/vsftpd/vsftpd.conf
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd/user_list
編輯user_list檔案.将使用者名添加進去
ftpuser
這時候發現,建立的使用者是可以通路其他路徑的,如果想要不允許,則編輯配置檔案,将這兩行前的#号去掉
chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd/chroot_list
如果沒有chroot_list檔案,則手動建立
touch chroot_list
編輯chroot_list檔案,将使用者賬号添加進去
如果發現vsftpd: refusing to run with writable root inside chroot錯誤
原因:從2.3.5之後,vsftpd增強了安全檢查,如果使用者被限定在了其主目錄下,則該使用者的主目錄不能再具有寫權限了!如果檢查發現還有寫權限,就會報該錯誤
解決:編輯配置檔案,在末尾加上
allow_writeable_chroot=YES
如果發現上傳不了檔案,則需要設定檔案夾讀寫權限
碰見的問題:
1.dos指令能連接配接,點選檢視這篇文章: FileZilla MLSD錯誤:連接配接逾時、讀取目錄清單失敗
2.dos指令能連接配接,但是windows連接配接不上,直接修改被動模式的端口,将最大端口和最小端口修改為一樣
整合nginx
1.安裝nginx參考這篇文章:https://www.cnblogs.com/wyd168/p/6636529.html
2.修改nginx配置檔案
通路效果:
如果這裡通路報404,則需要考慮指定的目錄是否有可通路權限
導入依賴:
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
實體類:
public class PicUploadResult {
private int error;
/**
* 圖檔儲存路徑
*/
private String url;
// set/get......
}
java上傳工具類:
import com.bbpk.common.base.ConstantInterface;
import com.bbpk.common.base.entity.vo.PicUploadResult;
import com.xiaoleilu.hutool.date.DateTime;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 檔案上傳幫助類
*/
public class FileUploadUtil {
public static boolean isImage(String contentType) {
for (String type : ConstantInterface.IMAGE_CONTENT_TYPE) {
if (contentType.toLowerCase().equals(type)) {
return true;
}
}
return false;
}
/**
* 照片上傳
*
* @param uploadFile 需上傳的檔案
* @return
* @throws Exception
*/
public static PicUploadResult imgUpload(MultipartFile uploadFile) throws Exception {
if (null == uploadFile) return null;
// 封裝Result對象,并且将檔案的byte數組放置到result對象中
PicUploadResult fileUploadResult = new PicUploadResult();
// 校驗圖檔格式
// boolean isLegal = isImageFile(uploadFile.getOriginalFilename());
boolean isLegal = isImage(uploadFile.getContentType());
// 狀态
fileUploadResult.setError(isLegal ? 0 : 1);
// 檔案新路徑
String fileName = getFileName(uploadFile.getContentType());
File newFile = new File(fileName);
InputStream is = uploadFile.getInputStream();
if (null == is) {
throw new Exception("圖檔輸入流為擷取失敗");
}
// 圖檔上傳到FTP伺服器
boolean rtn = FTPClientUtil.uploadImage("", newFile.getName(), is);
fileUploadResult.setUrl("http://IP+端口/"+newFile.getName());
fileUploadResult.setError(isLegal && rtn ? 0 : 1);
return fileUploadResult;
}
public static String getFileName(String contentType) {
String suffix = "";
List<String> type = Arrays.stream(ConstantInterface.IMAGE_CONTENT_TYPE)
.filter(n -> n.equals(contentType))
.collect(Collectors.toList());
if (type.size() > 0) {
suffix = StringUtils.substringAfterLast(type.get(0), "/");
}
Date nowDate = new Date();
return new DateTime(nowDate).toString("yyyyMMddhhmmssSSSS")
+ RandomUtils.nextInt(100, 9999) + "." + suffix;
}
}
import com.bbpk.common.base.ConstantInterface;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import java.io.*;
/**
* FTP用戶端 上傳檔案
*/
public class FTPClientUtil {
/**
* 校驗圖檔格式
*
* @param filename
* @return
*/
public static boolean isImageFile(String filename) {
// 校驗圖檔格式
boolean isLegal = false;
for (String type : ConstantInterface.IMAGE_TYPE) {
if (org.apache.commons.lang3.StringUtils.endsWithIgnoreCase(filename, type)) {
isLegal = true;
break;
}
}
return isLegal;
}
/**
* 擷取FTP連接配接
*
* @return
*/
private static FTPClient getInstance() {
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect("ip位址", 21);//連接配接FTP伺服器
//如果采用預設端口,可以使用ftp.connect(url)的方式直接連接配接FTP伺服器
boolean rtn = ftp.login("賬戶", "密碼");//登入
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
return ftp;
}
/**
* 上傳圖檔到伺服器
*
* @param relativePath 相對路徑
* @param filename 檔案名
* @param input 檔案流
* @return 成功傳回true,否則傳回false
*/
public static boolean uploadImage(String relativePath, String filename, InputStream input) {
return FTPClientUtil.uploadFile("/home/monkeyimg/img" + relativePath, filename, input);
}
/**
* 向FTP伺服器上傳檔案
*
* @param path FTP伺服器儲存目錄
* @param filename 上傳到FTP伺服器上的檔案名
* @param input 輸入流
* @return 成功傳回true,否則傳回false
*/
public static boolean uploadFile(String path, String filename, InputStream input) {
boolean success = false;
FTPClient ftpClient = getInstance();
ftpClient.enterLocalPassiveMode();
try {
ftpClient.setControlEncoding("UTF-8");
ftpClient.changeWorkingDirectory(path);
//如果是圖檔 需要修改上傳檔案的格式,否則圖檔以文本的形式傳輸,會失真
//ftpClient預設上傳的格式是文本
//修改成二進制上傳
if (isImageFile(filename)) {
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
}
//注意注意注意:需要設定目錄權限為777 坑死我了
success = ftpClient.storeFile(new String(filename.getBytes("UTF-8"), "iso-8859-1"), input);
input.close();
ftpClient.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException ioe) {
}
}
}
return success;
}
}