前些日子做项目的时候,有个需求是在上传文件的时候将文件在linux的ftp服务器上备份一下,搜了下,sftp能实现,因此做了以下操作实现了该功能。
下面这是网上找个一个sftp的工具类,在上传方法中调用该工具类中的方法实现sftp服务的连接,以及文件的上传。
package com.xz.cxzy.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Properties;
import java.util.Vector;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
public class SFTPUtil {
/**
* 连接sftp服务器
* @param host 主机
* @param port 端口
* @param username 用户名
* @param password 密码
* @return
*/
public static ChannelSftp connect(String host, int port, String username,
String password) {
ChannelSftp sftp = null;
try {
JSch jsch = new JSch();
jsch.getSession(username, host, port);
Session sshSession = jsch.getSession(username, host, port);
sshSession.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
System.out.println("Connected to " + host + ".");
} catch (Exception e) {
}
return sftp;
}
/**
* 上传文件
* @param directory 上传的目录
* @param uploadFile 要上传的文件
* @param sftp
*/
public void upload(String directory, String uploadFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
File file=new File(uploadFile);
sftp.put(new FileInputStream(file), file.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void upload(String directory,InputStream inputStream, String fileName,ChannelSftp sftp) {
try {
sftp.cd(directory);
sftp.put(inputStream,fileName);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载文件
* @param directory 下载目录
* @param downloadFile 下载的文件
* @param saveFile 存在本地的路径
* @param sftp
*/
public void download(String directory, String downloadFile,String saveFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
File file=new File(saveFile);
sftp.get(downloadFile, new FileOutputStream(file));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除文件
* @param directory 要删除文件所在目录
* @param deleteFile 要删除的文件
* @param sftp
*/
public static void delete(String directory, String deleteFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
sftp.rm(deleteFile);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 关闭连接
* @param sftp
*/
public static void disconnect(ChannelSftp sftp) {
if(sftp != null){
if(sftp.isConnected()){
sftp.disconnect();
}else if(sftp.isClosed()){
System.out.println("sftp is closed already");
}
}
}
/**
* 列出目录下的文件
* @param directory 要列出的目录
* @param sftp
* @return
* @throws SftpException
*/
public Vector listFiles(String directory, ChannelSftp sftp) throws SftpException{
return sftp.ls(directory);
}
public static void main(String[] args) {
//10.184.16.98 root ylj2013
SFTPUtil sf = new SFTPUtil();
String host = "liux服务器ip";
int port = 22;
String username = "root";
String password = "root";
String directory = "/u01/cxzyFiles/attach_upload/uploadfile/djzc/2013-12/";
String uploadFile = "F:/tempfiles/2_201083103325.png";
String downloadFile = "123.png";
String saveFile = "F:/tempfiles/2_201083103325_download.png";
String deleteFile = "b0e651d2-3cc9-4152-bb4c-d0b539cb7786.psd";
ChannelSftp sftp=sf.connect(host, port, username, password);
//sf.upload(directory, uploadFile, sftp);
//sf.download(directory, downloadFile, saveFile, sftp);
try{
sf.delete(directory, deleteFile, sftp);
disconnect(sftp);
//sftp.cd(directory);
//sftp.mkdir("ss");
System.out.println("finished");
}catch(Exception e){
e.printStackTrace();
}
}
}
下面是我项目中上传servlet中调用sftp的代码:
package com.xz.cxzy.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.jcraft.jsch.ChannelSftp;
import com.xz.cxzy.bean.NewsAttach;
import com.xz.cxzy.service.INewsAttachService;
import com.xz.cxzy.utils.SFTPUtil;
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = -7825355637448948879L;
private final String attachTempPath = "/attach_upload/tempfile";
private String attachUploadPath = "/attach_upload/uploadfile";
private final String hostIp = "linux服务器ip";
private final Integer hostPort = 22;
private final String userName = "root";
private final String password = "root";
private final String hostDistinctDir = "/u01/cxzyFiles/attach_upload/uploadfile/";//往服务器指定目录写文件
private boolean dirIsExists = true;
private boolean typeDirExists = true;
private String sftpSaveFileName = "";
private String sftpUploadFileName = "";
public FileUploadServlet() {
super();
}
/**处理上传路径
* @return
*/
private String getUpLoadPath(HttpServletRequest request,String dirType){
//拼接类型
String type = getActivedType(request,dirType);
if(!attachUploadPath.contains(type))
attachUploadPath = attachUploadPath+"/"+type;
//拼接日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
String ym = sdf.format(new Date());
if(!attachUploadPath.contains(ym))
attachUploadPath = attachUploadPath + "/" +ym;
return attachUploadPath;
}
private String getActivedType(HttpServletRequest request,String dirType){
//判断是属于哪个系统的上传 党建 or 外网管理
String type = dirType;
type = StringUtils.isNotBlank(type) ? type:"ylj";
return type;
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
INewsAttachService newsAttachService = (INewsAttachService) context.getBean("newsAttachService");
if(newsAttachService != null){
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存缓冲区,超过后写入临时文件
factory.setSizeThreshold(10240000);
// 设置临时文件存储位置
String base = this.getServletContext().getRealPath("/")+attachTempPath;
File file = new File(base);
if(!file.exists())
file.mkdirs();
factory.setRepository(file);
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置单个文件的最大上传值
upload.setFileSizeMax(10002400000l);
// 设置整个request的最大值
upload.setSizeMax(10002400000l);
upload.setHeaderEncoding("UTF-8");
try {
List<?> items = upload.parseRequest(request);
FileItem item = null;
// String fileName = null;
String resourceId = "";
String dirType_2 = "";
for (int i = 0 ;i < items.size(); i++){
item = (FileItem) items.get(i);
// fileName = uploadPath + File.separator + item.getName();
if(item.isFormField()){
String name = item.getFieldName();
if("news_id".equals(name)){
resourceId = item.getString();
}
if("dirType_2".equals(name)){
dirType_2 = item.getString();
attachUploadPath = getUpLoadPath(request,dirType_2);//改变上传路径
}
}
String uploadPath = this.getServletContext().getRealPath("/")+attachUploadPath;
File ufile = new File(uploadPath);
if(!ufile.exists()){
ufile.mkdirs();
}
// 保存文件
if (!item.isFormField() && item.getName().length() > 0) {
String suffix = FilenameUtils.getExtension(item.getName());//文件后缀
String saveFileName = StringUtils.join(new String[]{UUID.randomUUID().toString(), ".",suffix});
String uploadFileName = uploadPath + File.separator + saveFileName;
if(StringUtils.isNotBlank(resourceId)){
Integer r_id = Integer.parseInt(resourceId);
NewsAttach attach = new NewsAttach();
attach.setAttach_Name(item.getName());
attach.setAttach_real_path(uploadFileName);
attach.setResource_id(r_id);
attach.setAttach_path(attachUploadPath+"/"+saveFileName);
attach.setState("1");
newsAttachService.save(attach);
//往项目指定位置写文件
item.write(new File(uploadFileName));
sftpSaveFileName = saveFileName;
sftpUploadFileName = uploadFileName;
final String active_type = getActivedType(request,dirType_2);
new Thread(){
public void run() {
try {
//通过sftp方式往服务器指定目录写文件
ChannelSftp sftp = SFTPUtil.connect(hostIp, hostPort, userName, password);
if(sftp != null){
sftp.cd(hostDistinctDir);
//创建类型文件夹
try {
sftp.cd(active_type);
} catch (Exception e) {
typeDirExists = false;
}
if(!typeDirExists){
sftp.mkdir(active_type);
typeDirExists = true;
sftp.cd(active_type);
}
//创建日期文件夹
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
String ym = sdf.format(new Date());
try {
sftp.cd(ym);
} catch (Exception e) {
//出现异常说明文件在服务器上不存在
dirIsExists = false;
}
if(!dirIsExists) {
sftp.mkdir(ym);
dirIsExists = true;
}
SFTPUtil.upload(hostDistinctDir+active_type+"/"+ym, new FileInputStream(new File(sftpUploadFileName)), sftpSaveFileName, sftp);
SFTPUtil.disconnect(sftp);
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
在
FileUploadServlet 中,我是专门开了一个线程来处理sftp的文件上传。