Merge branch '15317-metrics'
[arvados.git] / sdk / java-v2 / src / main / java / org / arvados / client / logic / keep / FileDownloader.java
index 1f694f25c2dc2bc7297f570dbfcde7653a9e7353..5bfcabc10984bdb55a20bf130a2be0c88d819254 100644 (file)
@@ -23,6 +23,8 @@ import org.slf4j.Logger;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
@@ -70,6 +72,37 @@ public class FileDownloader {
         return downloadedFile;
     }
 
+    public File downloadFileWithResume(String collectionUuid, String fileName, String pathToDownloadFolder, long start, Long end) throws IOException {
+        if (end != null && end < start) {
+            throw new IllegalArgumentException("End index must be greater than or equal to the start index");
+        }
+
+        File destinationFile = new File(pathToDownloadFolder, fileName);
+
+        if (!destinationFile.exists()) {
+            boolean isCreated = destinationFile.createNewFile();
+            if (!isCreated) {
+                throw new IOException("Failed to create new file: " + destinationFile.getAbsolutePath());
+            }
+        }
+
+        try (RandomAccessFile outputFile = new RandomAccessFile(destinationFile, "rw");
+             InputStream inputStream = keepWebApiClient.get(collectionUuid, fileName, start, end)) {
+            outputFile.seek(start);
+
+            long remaining = (end == null) ? Long.MAX_VALUE : end - start + 1;
+            byte[] buffer = new byte[4096];
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1 && remaining > 0) {
+                int bytesToWrite = (int) Math.min(bytesRead, remaining);
+                outputFile.write(buffer, 0, bytesToWrite);
+                remaining -= bytesToWrite;
+            }
+        }
+
+        return destinationFile;
+    }
+
     public List<File> downloadFilesFromCollectionUsingKeepWeb(String collectionUuid, String pathToDownloadFolder) {
         String collectionTargetDir = setTargetDirectory(collectionUuid, pathToDownloadFolder).getAbsolutePath();
         List<FileToken> fileTokens = listFileInfoFromCollection(collectionUuid);
@@ -187,7 +220,7 @@ public class FileDownloader {
         // values for tracking file output streams and matching data chunks with initial files
         int currentDataChunkNumber;
         int bytesDownloadedFromChunk;
-        int bytesToDownload;
+        long bytesToDownload;
         byte[] currentDataChunk;
         boolean remainingDataInChunk;
         final List<KeepLocator> keepLocators;
@@ -199,11 +232,11 @@ public class FileDownloader {
             this.keepLocators = keepLocators;
         }
 
-        private int getBytesToDownload() {
+        private long getBytesToDownload() {
             return bytesToDownload;
         }
 
-        private void setBytesToDownload(int bytesToDownload) {
+        private void setBytesToDownload(long bytesToDownload) {
             this.bytesToDownload = bytesToDownload;
         }
 
@@ -244,7 +277,7 @@ public class FileDownloader {
 
         private void writeDownDataChunkPartially(FileOutputStream fos) throws IOException {
             //write all remaining bytes for this file from current chunk
-            fos.write(currentDataChunk, bytesDownloadedFromChunk, bytesToDownload);
+            fos.write(currentDataChunk, bytesDownloadedFromChunk, (int) bytesToDownload);
             // update number of bytes downloaded from this chunk
             bytesDownloadedFromChunk += bytesToDownload;
             // set remaining data in chunk to true