黑莓Java媒体文件在下载恢复时失真

问题描述:

我正在开发黑莓应用程序,我在恢复下载时遇到问题。如果下载没有中断,代码运行良好,但如果中断并重新开始下载,则媒体文件将失真。黑莓Java媒体文件在下载恢复时失真

要允许继续下载,我从服务器以块的形式请求文件并保留上次成功下载/写入的块。因此,如果我要重新启动下载,请检查上次下载和写入的块,然后增加它并使用它来确定从服务器请求的范围。我的代码如下..:

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; 
     } 
    } 

} 

所以我终于得到了这个工作。这是我做什么,希望对大家有所帮助的人,并从头痛拯救他们.. :)

如果我想恢复下载,我按照这个办法:

  1. 我检查了文件大小(根据RIM,fileSize对应于文件中包含的字节),并在文件结尾处打开outputStream。
  2. 我开始向服务器请求这个文件..例如,当链接关闭时,文件大小是500kb,我将开始请求范围500-(500 + chunkSize),直到我到达文件末尾。
  3. 并且该过程如问题所述继续