Возобновляемая загрузка Google Cloud не происходит - PullRequest
0 голосов
/ 09 января 2019

Мой код состоит из трех разделов

  • CustomDownloadProgressListener
  • Функция downloadToOutputStream (), в которой я написал код для загрузки файла из облачного хранилища
  • RetryHttpInitializerWrapper - обертка вокруг HttpRequestInitializer, как это предлагается в классе MediaHttpDownloader java doc на случай, если ответ плохой или сетевой брейки.

Тот же RetryHttpInitializerWrapper Я использовал для достижения возобновляемой загрузки и его работы, как и ожидалось, его загрузка в 10-10 МБ. Пожалуйста, предложите, что я здесь скучаю, потому что для одного запроса он работает нормально, но для повторной загрузки это не так. Я просто отключил свой интернет во время загрузки, чтобы протестировать перезапускаемый файл, но при повторном подключении он не возобновляет загрузку.

    public void downloadToOutputStream(String bucketName, String objectName, OutputStream data)
            throws IOException, GeneralSecurityException {
        GoogleCredential credential = GoogleCredential.getApplicationDefault();
        if (credential.createScopedRequired()) {
            credential = credential.createScoped(StorageScopes.all());
        }
        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        // custom HttpRequestInitializer for automatic retry upon failures.
        HttpRequestInitializer httpRequestInitializer = new RetryHttpInitializerWrapper(credential);

        GenericUrl requestUrl = new GenericUrl(
                "https://www.googleapis.com/storage/v1/b/" + bucketName + "/o/" + objectName);
        MediaHttpDownloader downloader = new MediaHttpDownloader(httpTransport, httpRequestInitializer);
        downloader.setProgressListener(new CustomDownloadProgressListener());
        downloader.download(requestUrl, data);
    }

    public class RetryHttpInitializerWrapper implements HttpRequestInitializer {
        private static final Logger LOG = Logger.getLogger(RetryHttpInitializerWrapper.class.getName());
        private final Credential wrappedCredential;
        private final Sleeper sleeper;
        private static final int MILLIS_PER_MINUTE = 60 * 1000;

        /**
         * A constructor using the default Sleeper.
         *
         * @param wrappedCredential
         *            the credential used to authenticate with a Google Cloud
         *            Platform project
         */
        public RetryHttpInitializerWrapper(Credential wrappedCredential) {
            this(wrappedCredential, Sleeper.DEFAULT);
        }

        /**
         * A constructor used only for testing.
         *
         * @param wrappedCredential
         *            the credential used to authenticate with a Google Cloud
         *            Platform project
         * @param sleeper
         *            a user-supplied Sleeper
         */
        RetryHttpInitializerWrapper(Credential wrappedCredential, Sleeper sleeper) {
            this.wrappedCredential = Preconditions.checkNotNull(wrappedCredential);
            this.sleeper = sleeper;
        }

        /**
         * Initialize an HttpRequest.
         *
         * @param request
         *            an HttpRequest that should be initialized
         */
        public void initialize(HttpRequest request) {
            request.setReadTimeout(2 * MILLIS_PER_MINUTE); // 2 minutes read
                                                            // timeout
            final HttpUnsuccessfulResponseHandler backoffHandler = new HttpBackOffUnsuccessfulResponseHandler(
                    new ExponentialBackOff()).setSleeper(sleeper);
            request.setInterceptor(wrappedCredential);
            request.setUnsuccessfulResponseHandler(new HttpUnsuccessfulResponseHandler() {
                public boolean handleResponse(final HttpRequest request, final HttpResponse response,
                        final boolean supportsRetry) throws IOException {
                    if (wrappedCredential.handleResponse(request, response, supportsRetry)) {
                        // If credential decides it can handle it, the return
                        // code or message indicated
                        // something specific to authentication, and no backoff
                        // is desired.
                        return true;
                    } else if (backoffHandler.handleResponse(request, response, supportsRetry)) {
                        // Otherwise, we defer to the judgement of our internal
                        // backoff handler.
                        System.out.println("Retrying " + request.getUrl().toString());
                        return true;
                    } else {
                        return false;
                    }
                }
            });
            request.setIOExceptionHandler(
                    new HttpBackOffIOExceptionHandler(new ExponentialBackOff()).setSleeper(sleeper));
        }
    }

 public class CustomDownloadProgressListener implements MediaHttpDownloaderProgressListener {
    public void progressChanged(MediaHttpDownloader downloader) {
        switch (downloader.getDownloadState()) {
        case MEDIA_IN_PROGRESS:
            System.out.println(downloader.getProgress());
            break;
        case MEDIA_COMPLETE:
            System.out.println("Download is complete!");
        }
    }
}

1 Ответ

0 голосов
/ 08 июля 2019

Я не публикую здесь никакого кода, но недавно мне удалось успешно возобновить загрузку из Google Cloud Storage с использованием заголовка Range.

Предположим, у меня есть 570-байтовый текстовый файл, который начинается с:

The next morning Hanna distracts Dieter

Если я отправлю заголовок Range со значением bytes=0-21, я получу обратно The next morning Hanna.

Если я отправлю заголовок Range со значением bytes=3-32, я получу обратно next morning Hanna distracts.

(ПРИМЕЧАНИЕ. В заголовке Range используется включающий интервал.)

Если размер моего чанка не превышает размер файла, и за исключением какой-либо сетевой ошибки, я всегда должен ожидать, что ответ будет содержать заголовок Content-Range, указывающий, какой диапазон байтов я только что скачал, а также общий размер файла. Например, ответ на мой первый запрос будет содержать Content-Range: bytes 0-21/570, поэтому мой следующий запрос будет иметь Range начало в байте 22, например, bytes=22-43.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...