Использование Java для * возобновляемых загрузок * с использованием * подписанного URL * в облачном хранилище Google - PullRequest
0 голосов
/ 15 января 2019

Исходя из документа о том, как создать объект в google-cloud-storage (см. Метод "create" в https://googleapis.github.io/google-cloud-java/google-cloud-clients/apidocs/index.html),, мы должны использовать метод blob.writer (...) при попытке загрузки большие файлы, поскольку он, по-видимому, каким-то образом автоматически обрабатывает возобновляемую загрузку. Это верно?

Однако, если мы хотим сделать возобновляемую загрузку по подписанным URL-адресам, как это можно сделать в Java? (Любой пример кода или указателей был бы очень признателен; до сих пор мои исследования привели меня к мысли, что невозможно использовать красиво созданные библиотеки java, и вместо этого нужно настраивать собственную логику, используя «PUT» и « POST "операторы в Java после того, как один сгенерировал подписанный URL. Это пока что" лучший "способ?)

1 Ответ

0 голосов
/ 15 января 2019

Что касается вашего первого пункта, да, метод blob.writer(...) автоматически обрабатывает возобновляемые загрузки. К сожалению, этот метод не вызывается из подписанного URL-адреса и загружает файлы только из потока байтов.

Однако, как вы упомянули, можно создать возобновляемую загрузку с подписанного URL-адреса другими методами, например, использование метода PUT кажется хорошим решением.

То, что я сделал, было следующим:

  1. Создайте подписанный URL методом «PUT». Вы можете сделать это, указав SignUrlOption , а также я указал учетную запись службы с необходимыми разрешениями в корзине.

  2. Используйте URLFetch , чтобы отправить HTTP-запрос на этот подписанный URL. Я считаю, что вы не можете использовать команду curl, например, напрямую, и UrlFetch API делает свое дело.

  3. Добавьте заголовок uploadType = resumable к HTTP-запросу urlFetch. См. эту документацию о том, как это работает, а также дополнительные параметры и информацию.

  4. Я настроил URLFetch на асинхронный вызов подписанного URL, так как я считаю, что это более удобно при загрузке больших файлов.

Пример кода, который будет использоваться в обработчике App Engine:

package com.example.storage;

import java.io.IOException;
import java.io.FileInputStream;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.HashMap;
import java.util.Map;
import java.nio.charset.StandardCharsets;

import java.net.URL;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// Cloud Storage Imports
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.storage.Blob;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage.SignUrlOption;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.cloud.storage.HttpMethod;

// Url Fetch imports
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.appengine.api.urlfetch.HTTPHeader;

@WebServlet(name = "MainStorage", value = "/")
public class MainStorage extends HttpServlet {

        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
                // Bucket parameters 
                String bucketName = "MY-BUCKET-NAME";
                String blobName = "MY-BLOB-NAME";
                String keyPath = "/PATH-TO-SERVICE-ACCOUNT-KEY/key.json";

                BlobId blobId = BlobId.of(bucketName, blobName);
                Storage storage = StorageOptions.getDefaultInstance().getService();

                // Create signed URL with SignUrlOptions
                URL signedUrl = storage.signUrl(BlobInfo.newBuilder(bucketName, blobName).build(), 14, TimeUnit.DAYS,
                                                SignUrlOption.signWith(ServiceAccountCredentials.fromStream(new FileInputStream(keyPath))),
                                                SignUrlOption.httpMethod(HttpMethod.PUT));

                // Contents to upload to the Blob
                String content = "My-File-contents";

                // Build UrlFetch request
                HTTPRequest upload_request = new HTTPRequest(signedUrl, HTTPMethod.PUT);
                upload_request.setPayload(content.getBytes(StandardCharsets.UTF_8));

                // Set request to have an uploadType=resumable
                HTTPHeader set_resumable = new HTTPHeader("uploadType", "resumable");
                upload_request.setHeader(set_resumable);
                URLFetchService fetcher = URLFetchServiceFactory.getURLFetchService();

                // Do an asynchronous call to the signed URL with the contents
                fetcher.fetchAsync(upload_request);

                // Return response to App Engine handler call
                response.setContentType("text/plain");
                response.getWriter().println("Hello Storage");
        }
}

Вероятно, это можно сделать лучше, но я думаю, что это дает представление о том, как можно сделать такое приложение.

...