短点续传方式实现下载音乐资源文件
主要思路: 在HTTP协议头中给定资源开始点,网络资源连接后便会从指定点下载资源.
String property = "bytes=" + startPos + "-";
sc.setRequestProperty("Range", property);
以下为实现代码:
1.核心代码
public class BreakPoint implements Runnable {
public int bufferSize = 1024;
public boolean stopThread = false;
public boolean stopDown = false;
private String fileURL;
private String httpURL;
public static long startPos; // 起始位置
public static long endPos; // 结束位置
public HttpConnection hc = null;
public DataInputStream dis = null;
public ByteArrayInputStream bis = null;
public LogFile logFile = null;
public ResourceFile resourceFile = null;
public BreakPoint(String fileURL, String httpURL) {
this.fileURL = fileURL;
this.httpURL = httpURL;
}
public void run() {
while (!stopThread) {
if (!stopDown) {
try {
logFile = new LogFile();
logFile.openFileConnection(ImusicMldlet.logFileUrl);
Hashtable hashTable = logFile.loadFromFile();
FileInfo fileInfo = (FileInfo) hashTable.get(fileURL);
// 如果为NULL是新资源
if (null == fileInfo) {
fileInfo = new FileInfo();
fileInfo.setHttpURL(httpURL);
fileInfo.setFileURL(fileURL);
fileInfo.setFileLength(getFileSize());
fileInfo.setCEndPos(0);
}
resourceFile = new ResourceFile();
resourceFile.openFileConnection(fileInfo.getFileURL());
startPos = fileInfo.getCEndPos();
// 建立文件startPos位置处添加通道
OutputStream ros = resourceFile.moveFilePoint(startPos);
// 建立远程资源指定startPos位置处HTTP连接
hc = HttpConnector.createHttpBpConnection(fileInfo
.getHttpURL(), HttpConnection.GET, 0, startPos);
dis = hc.openDataInputStream();
// 远程资源文件以bufferSize为单位写入本地文件
byte[] b = new byte[bufferSize];
endPos = fileInfo.getFileLength();
if (startPos < endPos) {
int nRead = (int) (endPos - startPos);
if (nRead > bufferSize) {
nRead = bufferSize;
}
while ((dis.read(b, 0, nRead)) > 0 && startPos <
endPos && !stopDown) {
resourceFile.write(ros, b, 0, nRead);
startPos = startPos + nRead;
nRead = (int) (endPos - startPos);
if (nRead > bufferSize) {
nRead = bufferSize;
}
}
if (startPos == endPos) {
stopThread = true; // 停止下载线程
stopDown = true;
}
if (stopDown) {
// 记录下载状态到数据库
fileInfo.cEndPos = startPos;
hashTable.put(fileURL, fileInfo);
logFile.saveLogFile(hashTable);
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
logFile.closeFileConnection();
resourceFile.close();
if (dis != null) {
dis.close();
}
if (bis != null) {
bis.close();
}
if (hc != null) {
hc.close();
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
}
}
public long getFileSize() {
long nFileLength = -1;
HttpConnection hc = null;
try {
hc = HttpConnector.createHttpConnection(httpURL, HttpConnection.GET, 0);
int responseCode = hc.getResponseCode();
if (responseCode >= 400) {
return -2;
}
nFileLength = hc.getLength();
} catch (Exception e) {
} finally {
try {
if (hc != null) {
hc.close();
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
return nFileLength;
}
}
2.HttpConnector 类实现网络连接
public class HttpConnector {
public static final int MAX_DATA_SIZE = 50 * 1024 * 1024;
public static String wapGateway = "http://10.0.0.172:80/";
public static boolean isCmWap = false;
public static HttpConnection createHttpConnection(String url,
String reqMethod, int contentLength) {
HttpConnection sc = null;
try {
if (isCmWap) {
String appIP = null; // 应用服务器地址
String appURI = url; // 路径
int n = appURI.indexOf("http://");
if (n != -1) {
appURI = appURI.substring(n + "http://".length(), appURI .length());
}
n = appURI.indexOf("/");
if (n != -1) {
appIP = appURI.substring(0, n);
appURI = appURI .substring(n + "/".length(), appURI.length());
} else {
appIP = appURI;
appURI = "";
}
StringBuffer buffer = new StringBuffer();
buffer.append(HttpConnector.wapGateway);
buffer.append(appURI);
url = buffer.toString();
System.out.println("Connector.open....." + url);
sc = (HttpConnection) Connector.open(url, Connector.READ_WRITE,
true);
sc.setRequestProperty("X-Online-Host", appIP);
sc.setRequestMethod(reqMethod);
if (reqMethod.equalsIgnoreCase(HttpConnection.POST)) {
sc.setRequestProperty("Content-Length", String
.valueOf(contentLength));
}
sc.setRequestProperty("Connection", "close");
} else {
System.out.println("Connector.open....." + url);
sc = (HttpConnection) Connector.open(url, Connector.READ_WRITE,
true);
sc.setRequestMethod(reqMethod);
if (reqMethod.equalsIgnoreCase(HttpConnection.POST)) {
sc.setRequestProperty("Content-Length", String
.valueOf(contentLength));
}
// sc.setRequestProperty("X-Up-Calling-Line-Id", "02087189489");
sc.setRequestProperty("Connection", "close");
}
} catch (Exception ex) {
ex.printStackTrace();
}
return sc;
}
public static HttpConnection createHttpBpConnection(String url,
String reqMethod, int contentLength, long startPos) {
HttpConnection sc = HttpConnector.createHttpConnection(url, reqMethod,
contentLength);
try {
if (startPos > 0) {
String property = "bytes=" + startPos + "-";
sc.setRequestProperty("Range", property);
sc.setRequestProperty("Connection", "close");
}
} catch (Exception ex) {
ex.printStackTrace();
}
return sc;
}
}
3.调用方式
httpBreakPoint = new BreakPoint(fileUrl, httpUrl);
Thread httpThread = new Thread(httpBreakPoint);
httpThread.start();
fileUrl为下载资源保存地址
httpUrl为下载资源网络地址
4.在上述过程中断点信息保存在断点日志文件中,每次下载会读取更新此文件,从而达到多个文件断点续传