我正在开发一个黑莓应用程序,但我在恢复下载时遇到了问题。如果下载没有中断,该代码运行良好,但如果中断并重新开始下载,则媒体文件会失真。
为了允许恢复下载,我从服务器请求文件块并保存最后一个成功下载/写入的块。因此,如果我要重新开始下载,我会检查最后下载和写入的块,增加它并使用它来确定从服务器请求的范围。我的代码如下所示..:
public final class Downloader extends Thread {
private String remoteName;
private String localName;
private String parentDir;
private String dirName;
public String fileName;
private int chunkSize = 512000;
public boolean completed = false;
public boolean failed = false;
public CacheObject cacheObject = null
public Downloader(String remoteName, String localName, String musicTitle, String parentDir, String dirName) {
this.remoteName = remoteName;
this.parentDir = parentDir;
this.dirName = dirName;
this.localName = localName;
this.secureDownload = false;
this.musicTitle = musicTitle;
this.cacheObject = CachedObject.getInstance().findCachedObject(musicTitle);
if (this.cacheObject == null) // create new object
this.cacheObject = new CachedObject(musicTitle, remoteName);
this.thisObj = this;
}
public void run() {
downloadFile(localName);
}
public void downloadFile(String fileName) {
try {
int chunkIndex = 0; int totalSize = 0;
String tempFileName = "file:///" + FileConnect.getInstance().FILE_ROOT+parentDir+ FileConnect.getInstance().FILE_SEPARATOR;
if (!FileConnect.getInstance().fileExists(tempFileName))
FileConnect.getInstance().createDirectory(parentDir);
if (dirName != null) {
tempFileName = "file:///" + FileConnect.getInstance().FILE_ROOT+ parentDir + "/" + dirName + FileConnect.getInstance().FILE_SEPARATOR;
if (!FileConnect.getInstance().fileExists(tempFileName))
FileConnect.getInstance().createDirectory(parentDir + "/" + dirName);
}
fileName = tempFileName + fileName;
this.fileName = fileName;
file = (FileConnection) Connector.open(fileName, Connector.READ_WRITE);
if (!file.exists()) {
file.create();
}
if(cacheObject.file_path.length() < 1)
cacheObject.file_path = fileName;
file.setWritable(true);
// Trying to check the file size.
long fSize = (int)file.fileSize();
// If it is greater than 1 byte, then we open an output stream at the end of the file
if(fSize > 1){
out = file.openOutputStream((fSize+1));
}
else{
out = file.openOutputStream();
}
int rangeStart = 0; int rangeEnd = 0;
// Want to know the total fileSize on server (used for updating the UI..
HttpConnection conn2;
conn2 = (HttpConnection) Util.getHttpConnection(remoteName);
String totalFileSize = "" + conn2.getLength();
conn2.close();
//Number of chunks
int numChunks = (int) Math.ceil( Integer.parseInt(totalFileSize) / chunkSize);
cacheObject.chunk_size = numChunks;
// Set the total file size..
content_length = Integer.parseInt(totalFileSize);
fileSize = 0;
String url = remoteName + HttpRequestDispatcher.getConnectionString();
if(cacheObject.last_successfully_downloaded_chunk > -1){
//This is a resume..
if( (cacheObject.last_successfully_downloaded_chunk + 1) < numChunks ){
chunkIndex = cacheObject.last_successfully_downloaded_chunk + 1;
fileSize = cacheObject.curr_download_size;
}
}
while (file != null) {
try{
conn = (HttpConnection)Connector.open(url);
if(chunkIndex < (numChunks-2)){
rangeStart = chunkIndex * chunkSize; rangeEnd = rangeStart + chunkSize - 1;
}
else{
rangeStart = chunkIndex * chunkSize;
int remainingBytes = Integer.parseInt(totalFileSize) - rangeStart; rangeEnd = rangeStart + (remainingBytes - 1);
}
conn.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0");
conn.setRequestProperty("Connection", "keep-alive");
conn.setRequestProperty("Range", "bytes=" + rangeStart + "-" + rangeEnd);
responseCode = conn.getResponseCode();
if (responseCode != 200 && responseCode != 206) {
out.flush(); out.close(); file.close(); in.close(); conn.close();
in = null; conn = null; file = null; out = null;
Thread.yield(); break;
}
else{
in = conn.openInputStream(); int length = -1;
byte[] readBlock = new byte[256];
while ((length = in.read(readBlock)) != -1) {
out.write(readBlock, 0, length);
fileSize += length;
cacheObject.curr_download_size = fileSize;
}
totalSize += fileSize;
in.close(); conn.close(); in = null; conn = null;
// Update after the byte read..
cacheMusicbox.last_successfully_downloaded_chunk = chunkIndex;
CachedObject.getInstance().saveCachedObject( cacheObject);
System.out.println("Last successful chunk downloaded: " + cacheObject.last_successfully_downloaded_chunk);
chunkIndex++;
if(chunkIndex == numChunks){
out.flush(); out.close(); file.close(); break;
}
Thread.yield();
}
}
// Network error related
catch(Exception e){
System.out.println("Download failed. Some kind of error - " + e.getMessage());
System.out.println("fileSize b4 closed: ." + file.fileSize());
System.out.println("Last successful chunk downloaded: " + cacheMusicbox.last_successfully_downloaded_chunk);
if (out != null) {
out.flush(); out.close();
System.out.println("We just closed the outputStream");
System.out.println("fileSize when closed: ." + file.fileSize());
}
if (file != null && file.exists()) {
if (file.isOpen()) {
file.close();
}
}
in = null; conn = null; file = null; out = null;
failed = true;
System.out.println("Ensuring this block is called " + cacheObject.last_successfully_downloaded_chunk);
break;
}
}
System.out.println("Full file downloaded: " + totalSize + " Bytes");
System.out.println("Wrote file to local storage");
Thread.sleep(3000);
if(!failed)
completed = true;
}
// any other error...
catch (Exception e) {
System.out.println(e.getMessage());
try{
out.flush(); out.close(); file.close();
in = null; conn = null; file = null; out = null;
}
catch(Exception ee){
System.out.println("While closing catch that belongs to the top guy: " + ee.getMessage());
}
failed = true;
}
}
}