package com.wouterbreukink.onedrive.tasks; import com.google.api.client.util.Preconditions; import com.wouterbreukink.onedrive.client.OneDriveItem; import com.wouterbreukink.onedrive.client.OneDriveUploadSession; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import static com.wouterbreukink.onedrive.CommandLineOpts.getCommandLineOpts; import static com.wouterbreukink.onedrive.LogUtils.readableFileSize; import static com.wouterbreukink.onedrive.LogUtils.readableTime; public class UploadTask extends Task { private static final Logger log = LogManager.getLogger(UploadTask.class.getName()); private final OneDriveItem parent; private final File localFile; private final boolean replace; public UploadTask(TaskOptions options, OneDriveItem parent, File localFile, boolean replace) { super(options); this.parent = Preconditions.checkNotNull(parent); this.localFile = Preconditions.checkNotNull(localFile); this.replace = replace; if (!parent.isDirectory()) { throw new IllegalArgumentException("Specified parent is not a folder"); } } public int priority() { return 50; } @Override public String toString() { return "Upload " + parent.getFullName() + localFile.getName(); } @Override protected void taskBody() throws IOException { if (isIgnored(localFile)) { reporter.skipped(); return; } if (localFile.isDirectory()) { OneDriveItem newParent = api.createFolder(parent, localFile); //noinspection ConstantConditions for (File f : localFile.listFiles()) { queue.add(new UploadTask(getTaskOptions(), newParent, f, false)); } } else { if (isSizeInvalid(localFile)) { reporter.skipped(); return; } long startTime = System.currentTimeMillis(); OneDriveItem response; if (localFile.length() > getCommandLineOpts().getSplitAfter() * 1024 * 1024) { int tryCount = 0; OneDriveUploadSession session = api.startUploadSession(parent, localFile); while (!session.isComplete()) { long startTimeInner = System.currentTimeMillis(); try { // We don't want to keep retrying infinitely if (tryCount == getCommandLineOpts().getTries()) { break; } api.uploadChunk(session); long elapsedTimeInner = System.currentTimeMillis() - startTimeInner; log.info(String.format("Uploaded chunk (progress %.1f%%) of %s (%s/s) for file %s", ((double) session.getTotalUploaded() / session.getFile().length()) * 100, readableFileSize(session.getLastUploaded()), elapsedTimeInner > 0 ? readableFileSize(session.getLastUploaded() / (elapsedTimeInner / 1000d)) : 0, parent.getFullName() + localFile.getName())); // After a successful upload we'll reset the tryCount tryCount = 0; } catch (IOException ex) { log.warn(String.format("Encountered '%s' while uploading chunk of %s for file %s", ex.getMessage(), readableFileSize(session.getLastUploaded()), parent.getFullName() + localFile.getName())); tryCount++; } } if (!session.isComplete()) { throw new IOException(String.format("Gave up on multi-part upload after %s retries", getCommandLineOpts().getTries())); } response = session.getItem(); } else { response = replace ? api.replaceFile(parent, localFile) : api.uploadFile(parent, localFile); } long elapsedTime = System.currentTimeMillis() - startTime; log.info(String.format("Uploaded %s in %s (%s/s) to %s file %s", readableFileSize(localFile.length()), readableTime(elapsedTime), elapsedTime > 0 ? readableFileSize(localFile.length() / (elapsedTime / 1000d)) : 0, replace ? "replace" : "new", response.getFullName())); reporter.fileUploaded(replace, localFile.length()); } } }