Package com.box.boxjavalibv2.filetransfer

Source Code of com.box.boxjavalibv2.filetransfer.BoxFileDownload

package com.box.boxjavalibv2.filetransfer;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import com.box.boxjavalibv2.IBoxConfig;
import com.box.boxjavalibv2.dao.BoxServerError;
import com.box.boxjavalibv2.exceptions.AuthFatalFailureException;
import com.box.boxjavalibv2.exceptions.BoxServerException;
import com.box.boxjavalibv2.jsonparsing.IBoxJSONParser;
import com.box.boxjavalibv2.requests.DownloadFileRequest;
import com.box.boxjavalibv2.requests.DownloadPartialFileRequest;
import com.box.boxjavalibv2.responseparsers.ErrorResponseParser;
import com.box.boxjavalibv2.utils.Constants;
import com.box.restclientv2.IBoxRESTClient;
import com.box.restclientv2.authorization.IBoxRequestAuth;
import com.box.restclientv2.exceptions.BoxRestException;
import com.box.restclientv2.requestsbase.BoxDefaultRequestObject;
import com.box.restclientv2.responseparsers.DefaultFileResponseParser;
import com.box.restclientv2.responses.DefaultBoxResponse;

/**
* Contains logic for downloading a user's file from Box API and supports using {@link IFileTransferListener} to monitor downloading progress.
*/
public class BoxFileDownload {

    /**
     * size of buffer used when reading from download input stream.
     */
    private static final int DOWNLOAD_BUFFER_SIZE = 4096;
    /**
     * The minimum time in milliseconds that must pass between each call to FileDownloadListener.onProgress. This is to avoid excessive calls which may lock up
     * the device.
     */
    private int progressUpdateInterval = 300;
    /** config. */
    private final IBoxConfig mConfig;
    /** File id. */
    private final String mFileId;
    /**
     * Used to track how many bytes have been transferred so far.
     */
    private long mBytesTransferred = 0;
    /** Listener to monitor downloading progress. */
    private IFileTransferListener mListener = null;
    /** REST client to make api calls. */
    private final IBoxRESTClient mRestClient;

    /**
     * Constructor.
     *
     * @param config
     *            config
     * @param restClient
     *            REST client to make api calls.
     * @param fileId
     *            Id of the file to be downloaded.
     */
    public BoxFileDownload(final IBoxConfig config, final IBoxRESTClient restClient, final String fileId) {
        this.mConfig = config;
        this.mFileId = fileId;
        this.mRestClient = restClient;
    }

    /**
     * Set the listener listening to download progress.
     *
     * @param listener
     *            listener
     */
    public void setProgressListener(final IFileTransferListener listener) {
        this.mListener = listener;
    }

    /**
     * Set the interval time you want the progress update to be reported.
     *
     * @param time
     *            interval time
     */
    public void setProgressUpdateInterval(final int time) {
        progressUpdateInterval = time;
    }

    /**
     * Return the interval time progress updates will be reported.
     *
     */
    public int getUpdateInterval() {
        return progressUpdateInterval;
    }

    /**
     * Execute a download.
     *
     * @param auth
     *            auth
     * @param outputStreams
     *            OutputStream's the file is going to be downloaded into.
     * @param parser
     *            json parser
     * @param requestObject
     *            request object
     * @throws BoxRestException
     *             exception
     * @throws IOException
     *             exception
     * @throws BoxServerException
     *             exception
     * @throws InterruptedException
     *             exception
     * @throws AuthFatalFailureException
     *             exception indicating authentication totally failed
     */
    public void execute(final IBoxRequestAuth auth, final OutputStream[] outputStreams, IBoxJSONParser parser, BoxDefaultRequestObject requestObject)
        throws BoxRestException, IOException, BoxServerException, InterruptedException, AuthFatalFailureException {
        InputStream result = execute(auth, parser, requestObject);
        copyOut(result, outputStreams);
    }

    /**
     * Execute a download.
     *
     * @param auth
     *            auth
     * @param destination
     *            destination file
     * @param parser
     *            json parser
     * @param requestObject
     *            request object
     * @throws BoxRestException
     *             exception
     * @throws IOException
     *             exception
     * @throws BoxServerException
     *             exception
     * @throws InterruptedException
     *             exception
     * @throws AuthFatalFailureException
     *             exception indicating authentication totally failed
     */
    public void execute(final IBoxRequestAuth auth, final File destination, IBoxJSONParser parser, BoxDefaultRequestObject requestObject)
        throws BoxRestException, IOException, BoxServerException, InterruptedException, AuthFatalFailureException {
        OutputStream[] streams = new OutputStream[1];
        streams[0] = new FileOutputStream(destination);
        execute(auth, streams, parser, requestObject);
    }

    /**
     * Execute the download and return the raw InputStream. This method is not involved with download listeners and will not publish anything through download
     * listeners. Instead caller handles the InputStream as she/he wishes.
     *
     * @param auth
     *            auth
     * @param parser
     *            json parser
     * @param requestObject
     *            request object
     * @return InputStream
     * @throws BoxRestException
     *             exception
     * @throws BoxServerException
     *             exception
     * @throws AuthFatalFailureException
     *             exception indicating authentication totally failed
     */
    public InputStream execute(final IBoxRequestAuth auth, IBoxJSONParser parser, BoxDefaultRequestObject requestObject) throws BoxRestException,
        BoxServerException, AuthFatalFailureException {
        DownloadFileRequest request;
        if (isPartialDownload(requestObject)) {
            request = new DownloadPartialFileRequest(mConfig, parser, mFileId, requestObject);
        } else {
            request = new DownloadFileRequest(mConfig, parser, mFileId, requestObject);
        }
        request.setAuth(auth);
        DefaultBoxResponse response = (DefaultBoxResponse) mRestClient.execute(request);
        DefaultFileResponseParser responseParser = new DefaultFileResponseParser();
        ErrorResponseParser errorParser = new ErrorResponseParser(parser);
        Object result = response.parseResponse(responseParser, errorParser);
        if (result instanceof BoxServerError) {
            throw new BoxServerException((BoxServerError) result);
        }
        return (InputStream) result;
    }

    /**
     * Get bytes transferred.
     *
     * @return the mBytesTransferred
     */
    public long getBytesTransferred() {
        return mBytesTransferred;
    }

    /**
     * Copy the InputStream into OutputStream's, also notify listener about the progress.
     *
     * @param inputStream
     *            InputStream
     * @param outputStreams
     *            OutputStream's
     * @throws IOException
     *             exception
     * @throws InterruptedException
     *             exception
     */
    private void copyOut(final InputStream inputStream, final OutputStream[] outputStreams) throws IOException, InterruptedException {
        // Read the rest of the stream and write to the destination
        // OutputStream.
        final byte[] buffer = new byte[DOWNLOAD_BUFFER_SIZE];
        int bufferLength = 0;
        long lastOnProgressPost = 0;
        try {
            while ((bufferLength = inputStream.read(buffer)) > 0) {
                if (Thread.currentThread().isInterrupted()) {
                    mListener.onProgress(mBytesTransferred);
                    mListener.onCanceled();
                    throw new InterruptedException();
                }
                for (int i = 0; i < outputStreams.length; i++) {
                    outputStreams[i].write(buffer, 0, bufferLength);
                }
                mBytesTransferred += bufferLength;
                long currTime = System.currentTimeMillis();
                if (mListener != null && currTime - lastOnProgressPost > progressUpdateInterval) {
                    lastOnProgressPost = currTime;
                    mListener.onProgress(mBytesTransferred);
                }
            }
        } catch (IOException e) {
            mListener.onIOException(e);
            mListener.onProgress(mBytesTransferred);
            mListener.onComplete(IFileTransferListener.STATUS_FAIL);
            throw e;
        } finally {
            // Try to flush and close all the OutputStreams and close
            // InputStream.
            IOException exception = null;
            for (int i = 0; i < outputStreams.length; i++) {
                try {
                    outputStreams[i].flush();
                    outputStreams[i].close();
                } catch (IOException e) {
                    exception = e;
                }
            }
            IOUtils.closeQuietly(inputStream);
            if (exception != null) {
                mListener.onIOException(exception);
                mListener.onProgress(mBytesTransferred);
                mListener.onComplete(IFileTransferListener.STATUS_FAIL);
                throw exception;
            }
        }
        mListener.onProgress(mBytesTransferred);
        mListener.onComplete(IFileTransferListener.STATUS_PASS);
    }

    // This is not officially supported, currently we only handles byte-range,
    // i.e. "Range".
    private boolean isPartialDownload(final BoxDefaultRequestObject requestObject) {
        boolean isRangeDownload = false;
        if (requestObject != null) {
            Object range = requestObject.getRequestExtras().getHeaders().get(Constants.RANGE);
            if (range instanceof String && StringUtils.isNotEmpty((String) range)) {
                isRangeDownload = true;
            }
        }
        return isRangeDownload;
    }
}
TOP

Related Classes of com.box.boxjavalibv2.filetransfer.BoxFileDownload

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.