java下载如何限速
解决方法:
1.核心方法
public static AtomicInteger downloadNum = new AtomicInteger();
@RequestMapping("/downloadFile")
public void downloadFile(HttpServletRequest request,HttpServletResponse response) {
downloadNum.incrementAndGet(); // 请求计数器 +1
OutputStream out = null;
InputStream fileInputStream = null;
DownloadLimiter downloadLimiter = null;
try {
String export_url ="F:/0f000Aq540QOO1Ne4OcXa6.xls";
String fileName=export_url.substring(export_url.lastIndexOf("/")+1);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition","attachment; filename=" + fileName);
fileInputStream = new FileInputStream(export_url );
//计算下载速度 总共的带宽是2M 速度是256KB/s
int downloadSpeed = 256/downloadNum.get();
BandwidthLimiter bandwidthLimiter = new BandwidthLimiter(downloadSpeed);
downloadLimiter = new DownloadLimiter(fileInputStream, bandwidthLimiter);
out = response.getOutputStream();
int len =0;
while((len=downloadLimiter.read()) != -1){
out.write(len);
bandwidthLimiter.setMaxRate(256/downloadNum.get());
}
out.flush();
out.close();
downloadLimiter.close();
} catch (IOException e) {
}finally{
if(fileInputStream !=null){
try {
fileInputStream.close();
} catch (IOException e) {
}
}
if(out !=null){
try {
out.close();
} catch (IOException e) {
}
}
if(downloadLimiter !=null){
try {
downloadLimiter.close();
} catch (IOException e) {
}
}
downloadNum.decrementAndGet(); // 请求计数器 -1
}
}
2.DownloadLimiter.java源码
import java.io.IOException;
import java.io.InputStream;
public class DownloadLimiter extends InputStream {
private InputStream is = null;
private BandwidthLimiter bandwidthLimiter = null;
public DownloadLimiter(InputStream is, BandwidthLimiter bandwidthLimiter) {
this.is = is;
this.bandwidthLimiter = bandwidthLimiter;
}
@Override
public int read() throws IOException {
if (this.bandwidthLimiter != null)
this.bandwidthLimiter.limitNextBytes();
return this.is.read();
}
public int read(byte b[], int off, int len) throws IOException {
if (bandwidthLimiter != null)
bandwidthLimiter.limitNextBytes(len);
return this.is.read(b, off, len);
}
}
3.BandwidthLimiter.java源码
public class BandwidthLimiter {
/* 1024KB */
private static Long KB = 1024l;
/* 以字节计算的最小计数块长度 */
private static Long CHUNK_LENGTH = 1024l;
/* 将发送或接收多少字节 */
private int bytesWillBeSentOrReceive = 0;
/* 当最后一块被发送或接收时 */
private long lastPieceSentOrReceiveTick = System.nanoTime();
/* 默认的速度是 1024KB/s */
private int maxRate = 256; //2M带宽是256KB/s
/* 时间成本来发送 CHUNK_LENGTH 字节纳秒 */
private long timeCostPerChunk = (1000000000l * CHUNK_LENGTH) / (this.maxRate * KB);
/**
* 初始化 a BandwidthLimiter object with a certain rate.
*
* @param maxRate
* the download or upload speed in KBytes
*/
public BandwidthLimiter(int maxRate) {
this.setMaxRate(maxRate);
}
/**
* Set the max upload or download rate in KB/s. maxRate must be grater than
* 0. If maxRate is zero, it means there is no bandwidth limit.
*
* 设置一个最大的下载速度,如果速度是0,这意味着没有带宽限制
* @param maxRate
* If maxRate is zero, it means there is no bandwidth limit.
* @throws IllegalArgumentException
*/
public synchronized void setMaxRate(int maxRate) throws IllegalArgumentException {
if (maxRate < 0) {
throw new IllegalArgumentException("maxRate can not less than 0");
}
this.maxRate = maxRate < 0 ? 0 : maxRate;
if (maxRate == 0)
this.timeCostPerChunk = 0;
else
this.timeCostPerChunk = (1000000000l * CHUNK_LENGTH) / (this.maxRate * KB);
}
/**
* Next 1 byte should do bandwidth limit.
* 下一个字节应该是带宽限制
*/
public synchronized void limitNextBytes() {
this.limitNextBytes(1);
}
/**
* 下一个len字节应该做带宽限制
*
* @param len
*/
public synchronized void limitNextBytes(int len) {
this.bytesWillBeSentOrReceive += len;
/* We have sent CHUNK_LENGTH bytes */
while (this.bytesWillBeSentOrReceive > CHUNK_LENGTH) {
long nowTick = System.nanoTime();
long missedTime = this.timeCostPerChunk - (nowTick - this.lastPieceSentOrReceiveTick);
if (missedTime > 0) {
try {
Thread.sleep(missedTime / 1000000, (int) (missedTime % 1000000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.bytesWillBeSentOrReceive -= CHUNK_LENGTH;
this.lastPieceSentOrReceiveTick = nowTick + (missedTime > 0 ? missedTime : 0);
}
}
}
本文链接:http://www.yayihouse.com/yayishuwu/chapter/1767