Skip to content
This repository has been archived by the owner on Sep 10, 2021. It is now read-only.

Commit

Permalink
ENH: refs #862. Pause/resume large download capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
zachmullen committed Oct 31, 2012
1 parent ff86406 commit 8f15c5b
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 38 deletions.
2 changes: 1 addition & 1 deletion core/controllers/DownloadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ public function appletAction()
{
$this->view->host = 'localhost';
}
$this->view->header = 'Large Data Download Applet';
$this->view->header = 'Large Data Downloader';
}

/**
Expand Down
Binary file modified core/public/java/uploader/dist/MidasUploader.jar
Binary file not shown.
130 changes: 104 additions & 26 deletions core/public/java/uploader/src/com/kitware/utils/DownloadThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ public class DownloadThread extends Thread
private Main parentUI;
private long uploadOffset = 0;
private int startIndex = 0;
private int currItem = 0;
private int currFolder = 0;
private String baseURL;
private String[] itemIds, folderIds;
private File dest, currentDir;
private boolean paused;
private boolean paused, first;
private FileOutputStream fileStream = null;

public static String IOEXCEPTION_ERROR_WRITING_REQUEST_BODY_TO_SERVER = "Error writing request body to server";

Expand All @@ -41,6 +44,7 @@ public DownloadThread(Main parentUI, String folderIds, String itemIds)
this.folderIds = folderIds.split(",");
this.itemIds = itemIds.split(",");
this.paused = false;
this.first = true;
}

public void forceClose()
Expand All @@ -56,21 +60,44 @@ public void run()
{
try
{
if(currItem == 0)
this.parentUI.setProgressIndeterminate(true);
Utility.log(Utility.LOG_LEVEL.DEBUG, "[CLIENT] " + this.getClass().getName() + " started");
for(int i = 0; i < folderIds.length; i++)
for(int i = currFolder; i < folderIds.length; i++)
{
if(!folderIds[i].trim().equals(""))
{
this.downloadFolderRecursive(folderIds[i], this.getFolderName(folderIds[i]), dest);
}
if(this.paused)
{
return;
}
else
{
this.parentUI.markTopLevelDownloadComplete();
currFolder++;
}
}
for(int i = 0; i < itemIds.length; i++)
for(int i = currItem; i < itemIds.length; i++)
{
if(!itemIds[i].trim().equals(""))
{
this.downloadItem(itemIds[i], dest);
}
if(this.paused)
{
return;
}
else
{
this.parentUI.markTopLevelDownloadComplete();
currItem++;
}
}
JOptionPane.showMessageDialog(this.parentUI, "Your download has finished.",
"Done", JOptionPane.INFORMATION_MESSAGE);
this.parentUI.progressBar.setValue(100);
}
catch (JavaUploaderException e)
{
Expand All @@ -80,6 +107,26 @@ public void run()
}
}

public int getCurrentFolder()
{
return this.currFolder;
}

public int getCurrentItem()
{
return this.currItem;
}

public void setCurrentFolder(int i)
{
this.currFolder = i;
}

public void setCurrentItem(int i)
{
this.currItem = i;
}

/**
* Helper method to get the http response as a string. Don't use for large responses,
* just smallish text ones.
Expand Down Expand Up @@ -121,15 +168,14 @@ private String getFolderName(String folderId) throws JavaUploaderException
throw new JavaUploaderException("Exception occurred on server when requesting folder name for id="+folderId);
}

return this.getResponseText().trim();
String name = this.getResponseText().trim();
conn.disconnect();
return name;
}
catch (IOException e)
{
throw new JavaUploaderException(e);
}
finally
{
conn.disconnect();
throw new JavaUploaderException(e);
}
}

Expand All @@ -142,7 +188,8 @@ private String getFolderName(String folderId) throws JavaUploaderException
private void downloadFolderRecursive(String folderId, String name, File directory) throws JavaUploaderException
{
String url = this.baseURL + "folder/javachildren?id=" + folderId;
// TODO update parent UI current resource name and count
this.parentUI.setFileNameLabel(name);
this.parentUI.resetCurrentDownload(-1);

File newDir = new File(directory, name);
if(!newDir.exists())
Expand Down Expand Up @@ -206,6 +253,11 @@ private void downloadFolderRecursive(String folderId, String name, File director
*/
private void downloadItem(String itemId, File directory) throws JavaUploaderException
{
if(first)
{
this.parentUI.setProgressIndeterminate(false);
first = false;
}
// First check if partially downloaded file exists. If so we append to it and pass an offset
long offset = 0;
boolean append = false;
Expand Down Expand Up @@ -240,56 +292,82 @@ private void downloadItem(String itemId, File directory) throws JavaUploaderExce

String name = conn.getHeaderField("Content-Disposition").split("=")[1];
name = name.replaceAll("\"", ""); //strip quotes from content disposition file name token
this.parentUI.setFileNameLabel(name);
this.parentUI.resetCurrentDownload(-1);
if (new File(directory, name).exists())
{
// skip the file if it has already been fully written
conn.disconnect();
// TODO increment progress in the parent UI by the length of the file on disk
this.parentUI.increaseDownloadProgress(new File(directory, name).length());
return;
}

if (conn.getContentLength() == -1)
long size = conn.getContentLengthLong();
if (size == -1)
{
// If this item is being ZipStreamed, we cannot resume, and must redownload it all (happens if head revision has > 1 bitstream)
append = false;
}
else
{
this.parentUI.resetCurrentDownload(size);
this.parentUI.increaseDownloadProgress(offset);
}

responseStream = new DataInputStream(conn.getInputStream());
FileOutputStream fileStream = new FileOutputStream(toWrite, append);
fileStream = new FileOutputStream(toWrite, append);
byte[] buf = new byte[1048576];
int len;
while ((len = responseStream.read(buf, 0, buf.length)) != -1)
{
fileStream.write(buf, 0, len);
// TODO increment parent UI progress by len
this.parentUI.increaseDownloadProgress((long)len);
}
fileStream.close();
responseStream.close();

fileStream.close();
// Final step: move the file to its completed name
toWrite.renameTo(new File(directory, name));
}
catch (IOException e)
{
String message = e.getMessage();
if (message != null
&& message.equals(IOEXCEPTION_ERROR_WRITING_REQUEST_BODY_TO_SERVER))
this.parentUI.setEnableResumeButton(true);
this.parentUI.setEnableUploadButton(false);
this.parentUI.setEnableStopButton(false);

if(this.paused)
{
Utility.log(Utility.LOG_LEVEL.WARNING, "[CLIENT] Catch IOException:"
+ IOEXCEPTION_ERROR_WRITING_REQUEST_BODY_TO_SERVER
+ " => Enable Resume");
this.parentUI.setEnableResumeButton(true);
this.parentUI.setEnableUploadButton(false);
this.parentUI.setEnableStopButton(false);
JOptionPane.showMessageDialog(this.parentUI, "Download paused. " +
"Press the Resume button to continue.",
"Connection problem", JOptionPane.INFORMATION_MESSAGE);
}
else
{
throw new JavaUploaderException(e);
this.paused = true;
Utility.log(Utility.LOG_LEVEL.WARNING, "[CLIENT] Catch IOException:"
+ IOEXCEPTION_ERROR_WRITING_REQUEST_BODY_TO_SERVER
+ " => Enable Resume");
JOptionPane.showMessageDialog(this.parentUI, "Error communicating with the server. " +
"Check your connection, then hit the Resume button.",
"Connection problem", JOptionPane.WARNING_MESSAGE);
}
}
finally
{
conn.disconnect();
try
{
conn.disconnect();
if(responseStream != null)
{
responseStream.close();
}
if(fileStream != null)
{
fileStream.close();
}
}
catch(Exception e)
{
}
}
}
}
Loading

0 comments on commit 8f15c5b

Please sign in to comment.