VSFTPD + NGINX

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

文档、资料和视频:

链接: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;
	
	@Override
	public 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")
	@ResponseBody
	public 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上传的工具类)

	@Override
	public 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;
	}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值