版权声明:本文为博主原创文章,转载请加入源链接。 https://blog.csdn.net/kevin_mails/article/details/79782103
工作中,有些环境带宽有限,比如说专线,通常带宽比较小,又不便宜,当业务量大的时间,如果在专线上还要传输文件的话,往往在文件传输的时间会导致带宽占慢,就有可能导致时实交易进不来,有可能影响交易,今天贴一下 jsch实现sftp文件上传,并且控制上传的速度,同时监控上传进度,供大家参考。
maven 工程下先把jsch 依赖添加到pom.xml
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
java 代码如下:
FileUploadMain.java
package com.sftp;
import com.jcraft.jsch.*;
import java.io.*;
import java.util.Properties;
/**
* 使用 JSch 上传文件,并且控制上传的速度,同时监控上传进度
*/
public class FileUploadMain {
public static void main(String[] args) {
JSch jsch = new JSch();
UploadMonitor monitor = null;
try {
Session session = jsch.getSession("ftpuser", "118.24.157.71", 22);
session.setPassword("Pass!112%");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp c = (ChannelSftp) channel;
String pwd = c.pwd();
System.out.println(pwd);
String src = "D:\\software\\apache-tomcat-6.0.36.zip";
String dst = c.pwd() + "/apache-tomcat-6.0.36.zip";
monitor = new UploadMonitor(new File(src).length());
//是否限制上传速度
boolean speedLimit = false;
if (speedLimit) {
OutputStream os = c.put(dst, monitor, ChannelSftp.OVERWRITE);
byte[] buff = new byte[1024 * 10]; // 设定每次传输的数据块大小为256KB
int read;
if (os != null) {
FileInputStream fis = new FileInputStream(src);
do {
read = fis.read(buff, 0, buff.length);
if (read > 0) {
os.write(buff, 0, read);
}
os.flush();
} while (read >= 0);
}
} else {
c.put(src, dst, monitor, ChannelSftp.OVERWRITE);
}
c.disconnect();
session.disconnect();
} catch (Exception e) {
/**
* 发生异常后,终止监听
*/
monitor.stop();
}
}
}
UploadMonitor.java
package com.sftp;
import com.jcraft.jsch.SftpProgressMonitor;
import java.text.NumberFormat;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author kevin.chen
*/
public class UploadMonitor implements SftpProgressMonitor, Runnable {
/**
* 文件的总大小
*/
private long maxCount = 0;
private long uploaded = 0;
long startTime = 0L;
private boolean isScheduled = false;
ScheduledExecutorService executorService;
public UploadMonitor(long maxCount) {
this.maxCount = maxCount;
}
/**
* 当文件开始传输时,调用init方法
*
* @param op
* @param src
* @param dest
* @param max
*/
@Override
public void init(int op, String src, String dest, long max) {
System.out.println("开始上传文件:" + src + "至远程:" + dest + "文件总大小:" + maxCount / 1024 + "KB");
startTime = System.currentTimeMillis();
}
/**
* 当每次传输了一个数据块后,调用count方法,count方法的参数为这一次传输的数据块大小
*
* @param count
* @return
*/
@Override
public boolean count(long count) {
if (!isScheduled) {
createTread();
}
uploaded += count;
System.out.println("本次上传大小:" + count / 1024 + "KB,");
if (count > 0) {
return true;
}
return false;
}
/**
* 当传输结束时,调用end方法
*/
@Override
public void end() {
}
/**
* 创建一个线程每隔一定时间,输出一下上传进度
*/
public void createTread() {
executorService = Executors.newSingleThreadScheduledExecutor();
//1秒钟后开始执行,每2杪钟执行一次
executorService.scheduleWithFixedDelay(this, 1, 2, TimeUnit.SECONDS);
isScheduled = true;
}
@Override
public void run() {
NumberFormat format = NumberFormat.getPercentInstance();
format.setMaximumFractionDigits(2);
format.setMinimumFractionDigits(2);
String value = format.format((uploaded / (double) maxCount));
System.out.println("已传输:" + uploaded / 1024 + "KB,传输进度:" + value);
if (uploaded == maxCount) {
stop();
long endTime = System.currentTimeMillis();
System.out.println("传输完成!用时:" + (endTime - startTime) / 1000 + "s");
}
}
public void stop() {
boolean isShutdown = executorService.isShutdown();
if (!isShutdown) {
executorService.shutdown();
}
}
}
在UploadMonitor类中,方法 public boolean count(long count) 因为每发送一次数据都会执行一次,比较频繁,所以我们单独创建一个线程定时查询一下上传进度
欢迎,收藏转载! 生产使用中需要再微调,比如日志打印