根据北京尚学堂公开教学视频学习

文档、资料和视频:

链接:https://pan.baidu.com/s/1i0zT9KUjNKpexvPHLi10xw 
提取码:eef4

壹、VSFTPD 简介

1、Linux 的组件(一款软件),安装到 Linux 后通过 java 代码(FtpClient)实 现文件上传

2、VSFTPD 基于 FTP 协议

3、为什么要使用 VSFTPD

3.1、之前实现文件上传

3.2 使用 VSFTPD 后优化

3.2.1、如果希望在客户端直接访问图片服务器中的图片,由于 VSFTPD 是基于 FTP 协议的,客户端浏览器是需要通过                      http 协议访 问图片.

3.2.2、解决办法使用 Nginx 进行反向代理

因为nginx只能代理http协议,对于和VSFTPD是不能被访问的,但是,我们可以将nginx和VSFTPD处于一台机器中,给Nginx操作VSFTPD的权利即可

4、可以使用格式在浏览器中访问到对应的图片(不推荐这样使用)

4.1 在谷歌浏览器中直接访问到 ftpuser 目录

4.2 在 IE 中访问的是 linux 的根目录

ftp://ftpuser:ftpuser@192.168.139.131

贰、FtpClient

1、java 技术,使用 FtpClient 使用使用 java 代码上传文件到 vsftpd 服务端

导入依赖

 <dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.6</version></dependency>

2、代码实例

package com.tk.ftpclient;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 Test {public static void main(String[] args) throws SocketException, IOException {FTPClient client = new FTPClient();//IP地址和端口号    写在登录之前client.connect("192.168.17.131", 21);//用户名和密码client.login("ftpuser", "1327148745");//设置文件类型client.setFileType(FTPClient.BINARY_FILE_TYPE); //在本机上找一张图片上传InputStream is = new FileInputStream("C:/Users/84741/Desktop/ssss/0.0.jpg");//设置上传目录    需要实现创建好文件,并赋予权限    client.changeWorkingDirectory("/home/ftpuser/aaa");//存储时的名称client.storeFile("abc11.jpg", is);//退出client.logout();//同名文件上传会覆盖原有内容System.out.println("上传成功");}
}

3、FtpUtil工具类

package com.tk.utils;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服务器// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器ftp.login(username, password);// 登录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.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("C:/Users/84741/Desktop/ssss/0.0.jpg"));  boolean flag = uploadFile("192.168.17.131", 21, "ftpuser", "1327148745", "/home/ftpuser","ccc", "abc2.png", in);  System.out.println(flag);  } catch (FileNotFoundException e) {  e.printStackTrace();  }  }
}

3. 使用 web 项目结合 FTPClient 完成

前台

 <form action="upload" method="post" enctype="multipart/form-data" ><input type="file"  name="file"/><input type="submit" value="上传"/></form>

控制器

    @RequestMapping("upload")public String upload(MultipartFile file) {try {boolean upload = uploadService.upload(file);if(upload) {return "success.jsp";}} catch (IOException e) {e.printStackTrace();}return "error.jsp";}

服务层

@Service
public class UploadServiceImpl implements UploadService{//使用软编码格式读取一些较为固定的数据@Value("${ftpclient.host}")private String host;@Value("${ftpclient.port}")private int port;@Value("${ftpclient.username}")private String username;@Value("${ftpclient.password}")private String password;@Value("${ftpclient.basePath}")private String basePath;@Value("${ftpclient.filePath}")private String filePath;@Overridepublic boolean upload(MultipartFile file) throws IOException {String fileName = UUID.randomUUID()+file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));System.out.println(fileName);return FtpUtil.uploadFile(host, port, username, password, basePath, filePath, fileName, file.getInputStream());}
}

软编码:ftpclient.properties(需要在applicationContext.xml文件中配置加载属性文件)

ftpclient.host = 192.168.17.131
ftpclient.port = 21
ftpclient.username = ftpuser
ftpclient.password = 1327148745
ftpclient.basePath = /home/ftpuser
ftpclient.filePath = /
<!-- 加载属性文件 --><context:property-placeholder location="classpath:jdbc.properties,classpath:ftpclient.properties "/>

叁、反向代理和正向代理

1、正向代理

1.1 客户端知道最终要访问的服务器地址(例如翻墙)

2. 反向代理

1.2 客户端只知道代理服务器地址,而不知道真实访问的服务器地址.

肆、nginx 配置(已经安装完成)

1. 进入到 nginx/conf 文件夹修改 nginx.conf

1.1 赋予 ftpuser 用户权限

1.2 设置代理的目录

1.2.1 root : 代理的目录

1.2.2 index: 欢迎项

1.2.3 如果只配置 root 不配置 index,在浏览器输入 ip 后依然报 403

完成一个简单的功能吧(基于SSM+VSFTPD+NGINX)

需求:类似于空间说说的上传,可以上传多张图片

数据库设计:(建表语句丢失了,直接看结构)

1、feel表:

2、picture表:

首先开启,VSFTPD服务,并且使用NGINX代理VSFTPD存储上传文件的空间

然后:正常的SSM开发流程

注意:

前台页面

使用了kindeditor里面的一些样式

图片是需要先单独上通过VSFTPD上传到存储空间中,就如图上图中的按钮批量上传,下图为详细

图片提交的  Controller

 @RequestMapping("upload")@ResponseBodypublic Map<String,Object> upload(MultipartFile imgFile){try {Map<String, Object> map = uploadService.upload(imgFile);return map;} catch (IOException e) {e.printStackTrace();}return null;}

图片提交 Service (利用FTP上传的工具类)

 @Overridepublic Map<String, Object> upload(MultipartFile imgFile) throws IOException {String fileName = UUID.randomUUID().toString()+imgFile.getOriginalFilename().substring(imgFile.getOriginalFilename().lastIndexOf("."));boolean result = FtpUtil.uploadFile(host, port, username, password, basePath, filePath, fileName, imgFile.getInputStream());Map<String, Object> map = new HashMap<String, Object>();if(result) {map.put("error", 0);map.put("url", "http://192.168.17.131/aaa/"+fileName);}else {map.put("error", 1);map.put("url", "图片上传失败!!!");}return map;}

返回map是因为kindeditor上传文件的返回格式为Json

kindeditor的文档

页面的代码

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<link rel="stylesheet" href="js/kindeditor-4.1.7/themes/default/default.css"/>
<script src="js/kindeditor-4.1.7/kindeditor.js"></script>
<script src="js/kindeditor-4.1.7/lang/zh_CN.js"></script>
<script>KindEditor.ready(function(K) {var editor = K.editor({allowFileManager : true,uploadJson:'upload'           //提交的地址});//富文本编辑器editor = K.create('textarea[name="feel"]', {uploadJson:'upload'           //提交的地址});//图片的提交K('#J_selectImage').click(function() {editor.loadPlugin('multiimage', function() {editor.plugin.multiImageDialog({clickFn : function(urlList) {var div = K('#J_imageView');div.html('');K.each(urlList, function(i, data) {div.append('<img src="' + data.url + '" width="50" height="50">');div.append('<input type="hidden" name="imgs" value="'+data.url+'" >');});editor.hideDialog();}});});});});
</script>
<body><form action="insert" method="post">标题:<input type="text" name="title"><br>图片:<input type="button" id="J_selectImage" value="批量上传" /><div id="J_imageView"></div>感受:<textarea name="feel" style="width:700px;height:200px;visibility:hidden;"></textarea><input type="submit" value="发布"></form></body>
</html>

上传说说信息(正常的上传操作)

控制器

 @RequestMapping("insert")public String insert(Feel feel,@RequestParam("imgs")List<String> imgs) {int index = uploadService.insFeel(feel, imgs);if(index > 0)return "success.jsp";return "error.jsp";}
public int insFeel(Feel feel, List<String> imgs) {//通过ID生成工具类生成ID      ——》时间戳+随机数long id = IDUtils.genItemId();feel.setId(id);//上传说说数据int index = feelMapper.insFeel(feel);if(index > 0) {//把图片也全部上传for (String string : imgs) {Picture picture = new Picture();picture.setFid(id);picture.setPath(string);index += pictureMapper.insPicture(picture);}//是否全部上传成功if(index ==imgs.size()+1) {return 1;}}return 0;}

VSFTPD + NGINX相关推荐

  1. ubuntu16.06+vsftpd+nginx搭建图片服务器

    安装vsftpd 注:以下指令都在root账户下操作 # apt安装vsftpd apt-get install vsftpd#启动vsftpd service vsftpd start#新建用户作为 ...

  2. linux中使用Vsftpd+nginx 搭建文件服务器

    目录标题 搭建文件服务器 1.安装 vsftpd 2.给文件服务器添加一个用户 3.设置开机自启动 vsftpd常用操作命令 安装Nginx 搭建文件服务器 1.安装 vsftpd yum -y in ...

  3. java从入门到精通_想要开始学java?你要的java从入门到精通布列如下!

    java从入门到精通,让我来告诉你! 毫无疑问,java是当下最火的编程语言之一.对于许多未曾涉足计算机编程的领域「小白」来说,深入地掌握java看似是一件十分困难的事.其实,只要掌握了科学的学习方法 ...

  4. java游戏_java开发的七个金典游戏你小时候肯定玩过

    相信很多刚接触编程的同学,对于Java开发能做些什么.做过哪些游戏, 并不是特别清楚.那么今天小编就为大家分享下, 万能的Java开发过的那些经典游戏吧! 手机上的Java即J2ME(Java 2 M ...

  5. python 单点登录_清华园计算机系联合推出的Java+Python视频曝光

    Java 和 Python 双方都有各自适合和发展的领域,所以别人常问我学习什么语言好,或者让我在两种语言进行比较好坏. 其实编程语言只有适不适合你个人去学,并不存在好坏,每种语言的存在即是合理的,你 ...

  6. java oracle管理系统_哔站播放量高达三百万的Java视频教程,如此惊人,还不来学?...

    "Java Planform Standard Edition"是Java语言的标准平台技术,是所有Java开发的语言基础,更是大数据.分布式开发思想建模的初期,此阶段的Java语 ...

  7. java之父_java之父:被下载达7000万次的编程视频教程,你还没有看过?

    "Java Planform Standard Edition"是Java语言的标准平台技术,是所有Java开发的语言基础,更是大数据.分布式开发思想建模的初期,此阶段的Java语 ...

  8. python免费全套教程400集视频-阿里巴巴大佬打造400集Python视频教程视频拿去,学完万物皆可爬...

    腾讯大厦 作为目前互联网时代,编程在里面有着意想不到的效果,开发APP,构建网络,制作游戏,感官视觉的提升等等,那么今天小编介绍的是经常在排行榜上齐头并进的2个编程语言,Java和Python. Ja ...

  9. 10.66道经典的Java基础面试题集锦为何晴空

    "JavaPlanformStandardEdition"是Java语言的标准平台技术,是所有Java开发的语言基础,更是大数据.分布式开发思想建模的初期,此阶段的Java语义.语 ...

最新文章

  1. Red Hat Enteripse Linux5下配置yum源的方法
  2. 浏览器加载和渲染html的顺序
  3. 大数据告诉你,中国女人有多勤奋
  4. LeetCode 1925. 统计平方和三元组的数目
  5. sql oracle 自增长字段,Oracle添加自增长字段方法步骤
  6. Java 工程师成神之路!
  7. JS规则 自加一,自减一 ( ++和- -) 【mynum = mynum + 1;//等同于mynum++;】
  8. Linux系统之备份与恢复
  9. 音乐流媒体服务器Navidrome
  10. 应届生面试反问环节该问什么,提高面试官好感
  11. 升压电路的原理-原文地址:http://www.52solution.com/basic/1218
  12. linux系统电视盒子到底是什么
  13. 百度搜索结果的URL参数 搜索历史记录(rsv_sug)
  14. python对于会计的好处_学好会计学的作用及意义
  15. 一个菜鸡的ACM之路
  16. python常用基础库:标准库和第三方库
  17. 中南大学python试卷_中南大学考研常见问题汇总
  18. Docker安装部署MySQL+Canal+Kafka+Camus+HIVE数据实时同步
  19. Android的媒体播放器——简易视频播放器(详解)
  20. 虚拟化及vmware产品介绍

热门文章

  1. visual studio 官网下载地址 vs2019/vs2017/vs2015企业版、专业版、社区版官网下载地址
  2. 想自己搭建服务器,永久运行网站?一个 U 盘大小的树莓派就够了!
  3. 关于wap上网及彩信的一点想法
  4. Uniapp苹果登录
  5. 求学者们论文的引用次数(中等难度C++)
  6. 西游记中孙悟空的家业历史
  7. 什么是大数据 大数据的特点
  8. python 输出秒 转成时分秒格式(1时40分21秒)
  9. 判断浏览器类型 (区分IE浏览器)
  10. ipad服务器未响应怎么办,ipad pro死机怎么办?ipad pro无反应解决方法