一、介绍
VSFTPD
vsftpd 是“very secure FTP daemon”的缩写,直译过来就是“非常安全的ftp协议守护程序” ,安全性是它的一个最大的特点。 vsftpd 是一个 UNIX 类操作系统上运行的服务器的名字,它可以运行在诸如 Linux、BSD、Solaris、 HP-UNIX 等系统上面,是一个完全免费的、开放源代码的 ftp 服务器软件,支持很多其他的 FTP 服务器所不支持的特征。
FTP协议
FTP 是 File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议”。 用于 Internet 上的控制文件的双向传输。同时,它也是一个应用程序(Application)。 基于不同的操作系统有不同的 FTP 应用程序,而所有这些应用程序都遵守同一种协议以传输文件。 在 FTP 的使用当中,用户经常遇到两个概念:“下载”(Download)和"上传"(Upload)。 "下载"文件就是从远程主机拷贝文件至自己的计算机上; "上传"文件就是将文件从自己的计 算机中拷贝至远程主机上。
二、几种图片服务器的区别
单体接口图片存储
在传统的单体架构项目中,可以在 web 项目中添加一个文件夹,来存放上传的图片。 例如在工程的根目录 WebRoot 下创建一个 images 文件夹用于保存已上传的图片。 优点:使用方便,便于管理 缺点: 1、如果是分布式环境中图片引用会出现问题。 2、图片的下载会给服务器增加额外的压力
存储结构
传统方式在分布式环境中遇到的问题
分布式环境的图片管理
用户上传时,通过负载均衡服务器将图片上传到ftp服务器上, 他是一个专门用于存储图片的服务器, 然后通过nginx反向代理, 使我们方便对文件的访问和下载 ,从而不会受限于单体接口图片存储的影响
三、安装与下载
安装vsftpd组件
yum -y install vsftpd
直接在linxu任意命令下,输入安装完后有/etc/vsftpd/vsftpd.conf 文件,是 vsftp 的配置文件。
添加一个linux用户
用来登陆ftp服务器
useradd ftpuser
这样一个用户建完,可以用这个登录。 登录后默认的路径为 /home/ftpuser.
给用户添加密码
passwd ftpuser
输入后根据提示修改密码,输入两次密码后修改密码
防火墙开启21端口
因为 ftp 默认的端口为 21,而 centos 默认是没有开启的,所以要修改 iptables 文件
vim /etc/sysconfig/iptables
如下图。然后: wq 保存并重启 iptables 防火墙。service iptables restart
修改selinux
外网是可以访问上去了,可是发现没法返回目录(使用 ftp 的主动模式,被动模式还是无法 访问),也上传不了,因为 selinux 作怪了。 执行以下命令查看状态: [root@bogon ~]#
getsebool -a | grep ftp
修改黄色部分属性的状态
执行以下命令修改,等待修改完成后再次查看其状态,都为on则进行下一步
代码语言:javascript复制[root@bogon ~]# setsebool -P allow_ftpd_full_access on
[root@bogon ~]# setsebool -P ftp_home_dir on
关闭匿名访问
修改fvsftpd的配置文件
vim /etc/vsftpd/vsftpd.conf
如下图,修改完毕后重启ftp服务service vsftpd restart
设置开机启动vsftp服务
chkconfig vsftpd on
如果不配置,则每次重启虚拟机是打开即可service vsftpd start
设置完毕以后,最好重启一下虚拟机,不然会出现bug,本人亲身经历!!!
测试是否成功
通过windows下的cmd访问,擦好看是否成功
配置Vsftpd的被动模式
被动模式默认开启,需要修改端口号的范围
代码语言:javascript复制[root@localhost ~]# vim /etc/vsftpd/vsftpd.conf
在防火墙中开放相关的端口(范围端口之间用的是冒号 )
代码语言:javascript复制[root@localhost ~]# vim /etc/sysconfig/iptables
四、图片的上传
使用FileZilla上传图片
端口21,双击即可上传
使用FTP协议访问图片服务器
前缀是ftp,浏览器默认是http,不要偷懒不写哦~~~
FTPClient工具
1、创建项目
2、在pom.xml通过坐标引入相关jar包( 该jar用于将文件封装成字节流的数据传输的功能 )
代码语言:javascript复制 <dependencies>
<!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
</dependencies>
3、手动编写上传测试代码
代码语言:javascript复制import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTPClient;
public class TestFtpClient {
public static void main(String[] args) throws SocketException, IOException {
//1、自己编写代码的方式
TestFtpClient t = new TestFtpClient();
t.FTPClientTest();//ftp://192.168.179.129/chy/aa.jpg
//2、使用工具类的实现
//InputStream is=new FileInputStream("F:/collection.jpg");
//FtpUtil.uploadFile("192.168.179.129", 21, "ftpuser", "ftpuser","/home/ftpuser/chy", "/2019/07/22", "chy666.jpg", is);
}
//ftpclient的使用
public void FTPClientTest() throws SocketException, IOException {
//创建ftp对象
FTPClient ftp = new FTPClient();
//链接 使用21端口
ftp.connect("192.168.179.129", 21);
//给定用户名和密码,链接时完成登录
ftp.login("ftpuser", "ftpuser");
//操作上传文件
InputStream is = new FileInputStream("F:/collection.jpg");
//设置为被动模式(如上传文件夹成功,不能上传文件,注释这行,否则报错refused:connect )
ftp.enterLocalPassiveMode();
//指定上传文件的保存目录
ftp.changeWorkingDirectory("/home/ftpuser/chy");
//开启字节流传输(默认字符流,会失真)
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
//文件上传
ftp.storeFile("bb.jpg", is);
//退出登陆
ftp.logout();
}
}
4、工具类实现上传下载
代码语言:javascript复制import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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;
/**
* ftp上传下载工具类
*/
public class FtpUtil {
/**
* Description: 向FTP服务器上传文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String host, int port, String username, String password, String basePath,
String filePath, String filename, InputStream input) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);// 连接FTP服务器
System.out.println("连接成功...");
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
System.out.println("洋洋登陆成功!!!");
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
//切换到上传目录
if (!ftp.changeWorkingDirectory(basePath filePath)) {
//如果目录不存在创建目录
String[] dirs = filePath.split("/");
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) continue;
tempPath = "/" dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
return result;
} else {
ftp.enterRemotePassiveMode();
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
//设置上传文件的类型为二进制类型
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//上传文件
if (!ftp.storeFile(filename, input)) {
return result;
}
input.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 要下载的文件名
* @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;
}
public static void main(String[] args) {
try {
FileInputStream in=new FileInputStream(new File("D:\1.png"));
boolean flag = uploadFile("192.168.179.129", 21, "ftpuser", "ftpuser", "/home/ftpuser/chy","/2015/01/21", "siliya1.png", in);
// FtpUtil.uploadFile("192.168.179.129", 21, "ftpuser", "ftpuser","/home/ftpuser/chy", "/2019/07/22", "chy.jpg", is);
System.out.println(flag);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
五、KindEditor
KindEditor 是一套开源的 HTML 可视化编辑器,主要用于让用户在网站上获得所见即 所得编辑效果,兼容 IE、Firefox、Chrome、Safari、Opera 等主流浏览器。 KindEditor 使用 JavaScript 编写,可以无缝与Java、.NET、 PHP、ASP 等程序接合。 KindEditor 非常适合在 CMS、商城、论坛、博客、Wiki、电子邮件等互联网应用上使用, 官网:http://kindeditor.net
六、基于KindEditor实现文件的上传
步骤:
- 创建一个parent项目,进行jar的管理
- 创建一个war项目kindEditorDemo,用于进行图片的上传与下载, 并且指定父项目是parent,额外添加tomcat插件
- 进行框架整合(web.xml springmvc.xml applicationContext-service.xml resource.properties)
- 导入相关的工具类(FtpUtil:FTPClient 工具类 IDUtils:生成一切 ID 的策略的工具类。可以使用他生成图片名称 JsonUtils:对象与 json 格式转换的工具类 )
- 在jsp中使用KindEditor 在项目中添加 KindEditor 与 Jquery 的 js 文件 在 JSP 页面中通过 script 标签引入 js 在 JSP 中添加 textarea 标签 调用 KindEditor 的 API 将 KindEditor 渲染到 textarea
注: KindEditor 初始化参数介绍 uploadJson:指定上传文件的服务器端程序 FilePostName:指定上传文件 form 名称。 dir:指定上传文件类型
代码
由于篇幅原因,请见下篇博文,附带源码分享
https://blog.csdn.net/qq_43371556/article/details/96980321