1.需求背景:跨服务器,将图片上传到新的服务器(图片服务器)保存
a.使用sftp的时候,经常报错ssh连接不对,换了jsch的jar进行开发、ftp工具类
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
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.InputStreamReader;
import java.io.OutputStream;
import java.util.Properties;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
/**
* FTP服务器工具类
*
*/
public class FTPUtils {
public static final String CHANNELTYPE_SFTP="sftp";
public static final String CHANNELTYPE_EXEC="exec";
private Session session;//会话
private Channel channel;//连接通道
private ChannelSftp sftp;// sftp操作类
private JSch jsch;
/*protected static String host=getLinuxParam()[0];
protected static String port=getLinuxParam()[1];
protected static String user=getLinuxParam()[2];
protected static String password=getLinuxParam()[3];*/
/*protected static String host="120.27.167.70";
protected static String port="6331";
protected static String user="ytyfemall";
protected static String password="ytyfemall";*/
protected static String host=ConfigManager.getString("file.host", "");;
protected static String port=ConfigManager.getString("file.port", "");;
protected static String user=ConfigManager.getString("file.user", "");;
protected static String password=ConfigManager.getString("file.password", "");;
private static String[] getLinuxParam(){
Properties props=new Properties();//读取文件类型创建对象。
try {
ClassLoader classLoader = FTPUtils.class.getClassLoader();// 读取属性文件
InputStream in = classLoader.getResourceAsStream("c");
props.load(in); /// 加载属性列表
if(in!=null){
in.close();
}
} catch (Exception e) {
System.out.println("Linux连接参数异常:"+e.getMessage());
}
String[] str={"","","",""};
str[0]=props.getProperty("file.host");
str[1]=props.getProperty("file.port");
str[2]=props.getProperty("file.user");
str[3]=props.getProperty("file.password");
return str;
}
/**
* 断开连接
*/
public static void closeConnect(Session session, Channel channel, ChannelSftp sftp){
if (null != sftp) {
sftp.disconnect();
sftp.exit();
sftp = null;
}
if (null != channel) {
channel.disconnect();
channel = null;
}
if (null != session) {
session.disconnect();
session = null;
}
System.out.println("连接已关闭");
}
/**
* 连接ftp/sftp服务器
*
* @param sftpUtil 类
*/
public static void getConnect(FTPUtils sftpUtil,String openChannelType) throws Exception {
Session session = null;
Channel channel = null;
JSch jsch = new JSch();
session = jsch.getSession(user, host, Integer.parseInt(port));
session.setPassword(password);
// 设置第一次登陆的时候提示,可选值:(ask | yes | no)
// 不验证 HostKey
session.setConfig("StrictHostKeyChecking", "no");
try {
session.connect();
} catch (Exception e) {
if (session.isConnected())
session.disconnect();
System.out.println("连接服务器失败");
}
channel = session.openChannel(openChannelType);
try {
channel.connect();
} catch (Exception e) {
if (channel.isConnected())
channel.disconnect();
System.out.println("连接服务器失败");
}
sftpUtil.setJsch(jsch);
if(openChannelType.equals(CHANNELTYPE_SFTP)){
sftpUtil.setSftp((ChannelSftp) channel);
}
sftpUtil.setChannel(channel);
sftpUtil.setSession(session);
}
/**
* 上传文件
*
* @param directory 上传的目录-相对于SFPT设置的用户访问目录
* @param uploadFile 要上传的文件全路径
*/
public static boolean upload(String directory, String uploadFile, String fileName) {
boolean resultState=false;
FTPUtils sftpUtil = new FTPUtils();
try{
getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
Session session = sftpUtil.getSession();
Channel channel = sftpUtil.getChannel();
ChannelSftp sftp = sftpUtil.getSftp();// sftp操作类
try {
sftp.cd(directory); //进入目录
} catch (SftpException sException) {
if (ChannelSftp.SSH_FX_NO_SUCH_FILE == sException.id) { //指定上传路径不存在
sftp.mkdir(directory);//创建目录
sftp.cd(directory); //进入目录
}
}
File file = new File(uploadFile);
InputStream in = new FileInputStream(file);
sftp.put(in, fileName);
in.close();
closeConnect(session, channel, sftp);
resultState=true;
}catch (Exception e){
System.out.println("上传文件异常");
}
return resultState;
}
/**
* 获取已连接的Sftp
* @return SftpUtil
*/
public static FTPUtils getConnectSftp(){
FTPUtils sftpUtil=new FTPUtils();
try {
getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
return sftpUtil;
}catch (Exception e){
System.out.println("下载文件异常");
}
return null;
}
/**
* 删除文件
* @param directory 要删除文件所在目录
* @param deleteFile 要删除的文件
*/
public static boolean delete(String directory, String deleteFile){
boolean resultState=false;
FTPUtils sftpUtil=new FTPUtils();
try {
getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
Session session = sftpUtil.getSession();
Channel channel = sftpUtil.getChannel();
ChannelSftp sftp = sftpUtil.getSftp();// sftp操作类
sftp.cd(directory); //进入的目录应该是要删除的目录的上一级
sftp.rm(deleteFile);//删除目录
closeConnect(session,channel,sftp);
resultState=true;
}catch (Exception e){
System.out.println("删除文件异常");
}
return resultState;
}
/**
JSch有三种文件传输模式:
(1)OVERWRITE:完全覆盖模式。JSch的默认文件传输模式,传输的文件将覆盖目标文件。
(2)APPEND:追加模式。如果目标文件已存在,则在目标文件后追加。
(3)RESUME:恢复模式。如果文件正在传输时,由于网络等原因导致传输中断,则下一次传输相同的文件
时,会从上一次中断的地方续传。
*/
/**
* 追加文件内容
* @param remoteFile 原文件路径
* @param in 追加内容
* @return true成功,false失败
*/
public static boolean appendFileContent(String remoteFile, InputStream in){
boolean resultState=false;
FTPUtils sftpUtil = new FTPUtils();
try{
getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
Session session = sftpUtil.getSession();
Channel channel = sftpUtil.getChannel();
ChannelSftp sftp = sftpUtil.getSftp();// sftp操作类
OutputStream out = sftp.put(remoteFile, ChannelSftp.APPEND);
int bufferSize=1024;
byte[] buff = new byte[bufferSize]; // 设定每次传输的数据块大小
int read;
if (out != null) {
do {
read = in.read(buff, 0, buff.length);
if (read > 0) {
out.write(buff, 0, read);
}
out.flush();
} while (read >= 0);
}
if(out!=null){
out.close();
}
closeConnect(session, channel, sftp);
resultState=true;
}catch (Exception e){
System.out.println("写入文件异常");
}
return resultState;
}
/**
* 创建文件
* @param fileDir 文件路径
* @param fileName 文件名称
* @return
*/
public static boolean createFile(String fileDir,String fileName){
try{
execute("mkdir -p "+fileDir+"\n" +
"touch "+fileDir+"/"+fileName);
}catch (Exception e){
return false;
}
return true;
}
/**
* 创建文件夹
* @param fileDir 文件路径
* @return true成功/false失败
*/
public static boolean createFileDir(String fileDir){
try{
execute("mkdir -p "+fileDir+"");
}catch (Exception e){
return false;
}
return true;
}
/**
* 压缩文件夹为ZIP
* @param fileDir 文件路径
* @param fileName 文件名称
* @param additionalName 压缩附加名
* @return
*/
public static boolean zipDir(String fileDir,String fileName,String additionalName){
try{
execute("cd "+fileDir+"\n" +
"zip -r "+fileDir+"/"+fileName+additionalName+".zip "+fileName);
}catch (Exception e){
return false;
}
return true;
}
/**
* 获取文件大小 单位(K)
* @param fileDir 文件路径
* @return 文件大小
*/
public static long getFileSize(String fileDir){
return Long.parseLong(execute("ls -l "+fileDir+" | awk '{ print $5 }'"));
}
/**
* 执行liunx 命令
* @param command 命令内容
* @return 命令输出
*/
public static String execute(String command){
FTPUtils sftpUtil=new FTPUtils();
StringBuffer strBuffer=new StringBuffer();
try {
getConnect(sftpUtil,CHANNELTYPE_EXEC);
// Create and connect session.
Session session = sftpUtil.getSession();
// Create and connect channel.
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
BufferedReader input = new BufferedReader(new InputStreamReader(channel
.getInputStream()));
channel.connect();
System.out.println("命令: " + command);
// 获取命令的输出
String line;
while ((line = input.readLine()) != null) {
strBuffer.append(line);
}
input.close();
closeConnect(session,channel,null);
} catch (Exception e) {
e.printStackTrace();
}
return strBuffer.toString();
}
}
b.main方法:
public static void main(String[] args) throws FileNotFoundException {
String window_dir="D:/testimg/QQ图片20200411163750.jpg";
String liunx_dir="/home/ytyfemall/upload/uxunimg/test/img";
try {
System.out.println(upload(liunx_dir,window_dir));
//System.out.println(download(liunx_dir,"test.txt","C:\\Users\\XXX\\Desktop\\test"));
System.out.println(delete(liunx_dir,"test.txt"));
InputStream inputStream = new ByteArrayInputStream("this is test".getBytes());
System.out.println(appendFileContent(liunx_dir+"/test.txt",inputStream));
String command="touch /usr/local/longlin/longpizi.sh\nmkdir -p sss";
System.out.println(execute(command));
//System.out.println(createFile("/home/ytyfemall/upload/uxunimg/test","sss.txt"));
System.out.println(upload(liunx_dir,window_dir));
} catch (Exception e) {
e.printStackTrace();
}
}
c.代码中使用,本人使用的框架(SSH+Spring+Hib)
在action中找到service
goodsService.updateGoodsInfoEmall(goodsInfoEmall,file,fileName,uplodfile);
service的实现类实现该方法:
// 上传图片信息
if( file != null && fileName != null ){
fileName = DateUtils.dateToDateString(new Date(), DateUtils.TIME_STR_FORMAT);
String getResponse = uploadImageSFCP(file, fileName, goodsInfo.getGoodsid(),"1");
}
if(uploadfile != null ){
if(uploadfile.length>0){
for(int index=0;index<uploadfile.length;index++){
fileName = DateUtils.dateToDateString(new Date(), DateUtils.TIME_STR_FORMAT);
String fname = fileName+"_"+index;
String getResponse = uploadImageSFCP(uploadfile[index], fname, goodsInfo.getGoodsid(),"2");
}
}
}
具体上传实现:
public String uploadImageSFCP(File file, String fileName, String goodsId, String imgtype) throws Exception {
log.debug("[file]--" + file);
log.debug("[file name]--" + fileName);
String serverRootdir = ServletActionContext.getServletContext().getRealPath(Constant.IMAGE_SAVE_FOLDER).replace(ConfigManager.getString("uxun.plat.name", "uxunplat"), ConfigManager.getString("uxun.cust.name", "jfycust"));
String serverRootSubdir ="/" + goodsId;
FileUtil.createFolder(serverRootdir + serverRootSubdir);
// 创建文件夹
String beShowedPath = serverRootSubdir+serverRootSubdir+"_"+fileName+".jpg";
log.info("=============>存储有地址:" + serverRootdir + beShowedPath);
String yyzxPath = ConfigManager.getString("YYZX_IMAGE_URL", "");
String windowPathString = file.getAbsolutePath();
String linuxPathString = yyzxPath+goodsId;
String fileNameString = goodsId+"_"+fileName+".jpg";
FTPUtils.upload(linuxPathString, windowPathString, fileNameString);
log.info("===============>linuxPathString:"+linuxPathString);
log.info("===============>windowPathString:"+windowPathString);
log.info("===============>fileNameString:"+fileNameString);
}
服务器地址,本机地址,文件名称都需要自己去写,
PS:有个问题就是file上传的时候,会先找到tomcat容器下的.temp临时文件,所以上传后需要自行修改后缀名称,当然你要两台服务器可以连通,user,password,port,url都要有具体