diff --git a/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java b/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java index cbc86548..94ac1ec9 100644 --- a/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java +++ b/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java @@ -616,4 +616,6 @@ public abstract class AbstractRipper // If true ripme uses a byte progress bar protected boolean useByteProgessBar() { return false;} + // If true ripme will try to resume a broken download for this ripper + protected boolean tryResumeDownload() { return false;} } diff --git a/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java b/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java index 768e1c12..45c72c6e 100644 --- a/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java +++ b/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java @@ -59,28 +59,25 @@ class DownloadFileThread extends Thread { this.cookies = cookies; } - private int getTotalBytes(URL url) throws IOException { - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("HEAD"); - conn.setRequestProperty("accept", "*/*"); - conn.setRequestProperty("Referer", this.url.toExternalForm()); // Sic - conn.setRequestProperty("User-agent", AbstractRipper.USER_AGENT); - return conn.getContentLength(); - } - /** * Attempts to download the file. Retries as needed. * Notifies observers upon completion/error/warn. */ public void run() { + long fileSize = 0; + int bytesTotal = 0; + int bytesDownloaded = 0; + if (saveAs.exists() && observer.tryResumeDownload()) { + fileSize = saveAs.length(); + } try { observer.stopCheck(); } catch (IOException e) { observer.downloadErrored(url, "Download interrupted"); return; } - if (saveAs.exists()) { + if (saveAs.exists() && !observer.tryResumeDownload()) { if (Utils.getConfigBoolean("file.overwrite", false)) { logger.info("[!] Deleting existing file" + prettySaveAs); saveAs.delete(); @@ -90,22 +87,6 @@ class DownloadFileThread extends Thread { return; } } - - int bytesTotal, bytesDownloaded = 0; - if (observer.useByteProgessBar()) { - try { - bytesTotal = getTotalBytes(this.url); - } catch (IOException e) { - logger.error("Failed to get file size at " + this.url, e); - observer.downloadErrored(this.url, "Failed to get file size of " + this.url); - return; - } - - observer.setBytesTotal(bytesTotal); - observer.sendUpdate(STATUS.TOTAL_BYTES, bytesTotal); - logger.debug("Size of file at " + this.url + " = " + bytesTotal + "b"); - } - URL urlToDownload = this.url; boolean redirected = false; int tries = 0; // Number of attempts to download @@ -139,11 +120,20 @@ class DownloadFileThread extends Thread { cookie += key + "=" + cookies.get(key); } huc.setRequestProperty("Cookie", cookie); + if (observer.tryResumeDownload()) { + if (fileSize != 0) { + huc.setRequestProperty("Range", "bytes=" + fileSize + "-"); + } + } logger.debug("Request properties: " + huc.getRequestProperties()); huc.connect(); int statusCode = huc.getResponseCode(); logger.debug("Status code: " + statusCode); + if (statusCode != 206 && observer.tryResumeDownload()) { + // TODO find a better way to handle servers that don't support resuming downloads then just erroring out + throw new IOException("Server doesn't support resuming downloads"); + } if (statusCode / 100 == 3) { // 3xx Redirect if (!redirected) { // Don't increment retries on the first redirect @@ -171,6 +161,15 @@ class DownloadFileThread extends Thread { observer.downloadErrored(url, "Imgur image is 404: " + url.toExternalForm()); return; } + + // If the ripper is using the bytes progress bar set bytesTotal to huc.getContentLength() + if (observer.useByteProgessBar()) { + bytesTotal = huc.getContentLength(); + observer.setBytesTotal(bytesTotal); + observer.sendUpdate(STATUS.TOTAL_BYTES, bytesTotal); + logger.debug("Size of file at " + this.url + " = " + bytesTotal + "b"); + } + // Save file bis = new BufferedInputStream(huc.getInputStream()); @@ -179,8 +178,12 @@ class DownloadFileThread extends Thread { String fileExt = URLConnection.guessContentTypeFromStream(bis).replaceAll("image/", ""); saveAs = new File(saveAs.toString() + "." + fileExt); } - - fos = new FileOutputStream(saveAs); + // If we're resuming a download we append data to the existing file + if (statusCode == 206) { + fos = new FileOutputStream(saveAs, true); + } else { + fos = new FileOutputStream(saveAs); + } byte[] data = new byte[1024 * 256]; int bytesRead; while ( (bytesRead = bis.read(data)) != -1) { try {