根据北京尚学堂公开教学视频学习
文档、资料和视频:
链接:https://pan.baidu.com/s/1i0zT9KUjNKpexvPHLi10xw
提取码:eef4
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:[email protected]
1、java 技术,使用 FtpClient 使用使用 java 代码上传文件到 vsftpd 服务端
导入依赖
commons-net
commons-net
3.6
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 完成
前台
控制器
@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 = /
1.1 客户端知道最终要访问的服务器地址(例如)
1.2 客户端只知道代理服务器地址,而不知道真实访问的服务器地址.
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
需求:类似于空间说说的上传,可以上传多张图片
数据库设计:(建表语句丢失了,直接看结构)
1、feel表:
2、picture表:
首先开启,VSFTPD服务,并且使用NGINX代理VSFTPD存储上传文件的空间
然后:正常的SSM开发流程
注意:
前台页面
使用了kindeditor里面的一些样式
图片是需要先单独上通过VSFTPD上传到存储空间中,就如图上图中的按钮批量上传,下图为详细
图片提交的 Controller
@RequestMapping("upload")
@ResponseBody
public Map upload(MultipartFile imgFile){
try {
Map map = uploadService.upload(imgFile);
return map;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
图片提交 Service (利用FTP上传的工具类)
@Override
public Map 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 map = new HashMap();
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"%>
Insert title here
控制器
@RequestMapping("insert")
public String insert(Feel feel,@RequestParam("imgs")List imgs) {
int index = uploadService.insFeel(feel, imgs);
if(index > 0)
return "success.jsp";
return "error.jsp";
}
public int insFeel(Feel feel, List 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;
}