Хотя ответ на несколько вопросов в одном ответе обычно не подходит для Stackoverflow, кажется, что все они тесно связаны и поэтому дадут обзор возобновляемых загрузок и при этом попытайтесь решить три ваших вопроса:
- Как получить общее количество байтов, уже загруженных на диск
- Как использовать значение в заголовке Content-Range
- Как приостановить возобновляемую загрузку
Из документации Google на Прямая и возобновляемая загрузка носителей на Java Документация клиентской библиотеки API:
Детали реализации
Основные интересующие классы: MediaHttpUploader и MediaHttpProgressListener .
Если методы в сгенерированных c библиотеках, специфичных для службы, содержат параметр mediaUpload
в документе Discovery для этих методов создается удобный метод, который принимает InputStreamContent в качестве параметра. * 10 30 *
Например, метод insert
Drive API поддерживает mediaUpload
, и вы можете использовать следующий код для загрузки файла:
class CustomProgressListener implements MediaHttpUploaderProgressListener {
public void progressChanged(MediaHttpUploader uploader) throws IOException {
switch (uploader.getUploadState()) {
case INITIATION_STARTED:
System.out.println("Initiation has started!");
break;
case INITIATION_COMPLETE:
System.out.println("Initiation is complete!");
break;
case MEDIA_IN_PROGRESS:
System.out.println(uploader.getProgress());
break;
case MEDIA_COMPLETE:
System.out.println("Upload is complete!");
}
}
}
File mediaFile = new File("/tmp/driveFile.jpg");
InputStreamContent mediaContent =
new InputStreamContent("image/jpeg",
new BufferedInputStream(new FileInputStream(mediaFile)));
mediaContent.setLength(mediaFile.length());
Drive.Files.Insert request = drive.files().insert(fileMetadata, mediaContent);
request.getMediaHttpUploader().setProgressListener(new CustomProgressListener());
request.execute();
Однако эти классы абстрактны удалите такие вещи, как URI местоположения, который возвращается при создании возобновляемой загрузки, поэтому, если вы хотите иметь возможность это сделать, вам нужно будет выполнить шаги инициации возобновляемой загрузки, как описано здесь . Однако все это делается вручную, а не напрямую с использованием клиентской библиотеки Google Drive API.
Чтобы ответить на первый вопрос, вам решать, как вы сохраните, сколько байтов было загружено. Вместо того, чтобы думать «сколько уже на диске» , подумайте «сколько я уже загрузил?» .
Вы можете сохранить это как переменную локально, если хотите, так как он будет кратен размеру вашего блока (2 * MediaHttpUploader.MINIMUM_CHUNK_SIZE
в вашем случае) и его будет легко отслеживать.
Дело в том, что на самом деле это не нужно. Вы можете просто использовать подстановочный знак, чтобы указать, что текущая позиция вашего файла неизвестна в соответствии с документацией (выделено мной):
Если запрос на загрузку завершается до ответа, или если вы получите ответ 503 Service Unavailable, затем вам необходимо возобновить прерванную загрузку.
Чтобы запросить статус загрузки, создайте пустой запрос PUT
к URI возобновляемого сеанса.
Добавьте заголовок Content-Range
, чтобы указать, что текущая позиция в файле неизвестна. Например, установите Content-Range
на */2000000
, если общая длина файла составляет 2 000 000 байт. Если вы не знаете полный размер файла, установите Content-Range
на */*
.
Если вы хотите отслеживать байты, вы можете указать его в заголовке Content-Range
как
Content-Range: bytes_so_far/total_bytes
Шаги:
Для инициализации возобновляемой загрузки, вам необходимо сделать запрос POST
к конечной точке /upload
Drive API. Вам не нужно использовать для этого клиентскую библиотеку Drive API (и на самом деле, если вы хотите получить URI возобновляемого сеанса, вы не можете этого сделать, поскольку клиентская библиотека не дает вам этого).
Предполагая, что вы иметь определение ваших учетных данных из:
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(...);
Затем сделайте запрос POST
, содержащий метаданные файла:
URL requestUrl = new URL("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable");
String requestBody = "{\"name\": \"fileName\"}";
HttpURLConnection request = (HttpURLConnection) requestUrl.openConnection();
request.setRequestMethod("POST");
request.setDoInput(true);
request.setDoOutput(true);
request.setRequestProperty("Authorization", "Bearer " + credential.getToken());
request.setRequestProperty("X-Upload-Content-Type", "file/mimetype");
request.setRequestProperty("X-Upload-Content-Length", number_of_bytes_of_your_file);
request.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
request.setRequestProperty("Content-Length", String.format(Locale.ENGLISH, "%d", requestBody.getBytes().length));
OutputStream outputStream = request.getOutputStream();
outputStream.write(requestBody.getBytes());
outputStream.close();
request.connect();
URI сеанса - куда позвонить, чтобы возобновить, если вам нужно - возвращается в заголовках ответа от API. После подключения вы можете получить этот URI из ответа:
if (request.getResponseCode() == HttpURLConnection.HTTP_OK) {
URL sessionUri = new URL(request.getHeaderField("location"));
}
Теперь у вас есть URI сеанса - с его помощью вы можете загружать фрагменты файла на Диск по своему усмотрению. Теперь вам нужно использовать этот URI в качестве точки загрузки для последующих загрузок.
Однако помните: URI возобновляемого сеанса истекает через неделю.
Как приостановить возобновляемую загрузку:
Это на самом деле все зависит от того, как вы sh это реализовать. Например, вы можете выделить al oop или иметь гигантскую кнопку PAUSE THIS UPLOAD
в GUI, которая переключает, будет ли продолжаться следующий раздел загрузки или нет.
Следует помнить, что при загрузке содержимое файла, запрос должен быть выполнен с использованием HTTP PUT
, а не POST
. Следуя предыдущему разделу:
// set these variables:
long beginningOfChunk = 0;
long chunkSize = 2 * MediaHttpUploader.MINIMUM_CHUNK_SIZE;
int chunksUploaded = 0;
// Here starts the upload chunk code:
HttpURLConnection request = (HttpURLConnection) sessionUri.openConnection();
request.setRequestMethod("PUT");
request.setDoOutput(true);
// change your timeout as you desire here:
request.setConnectTimeout(30000);
request.setRequestProperty("Content-Type", "file/mimetype");
long bytesUploadedSoFar = chunksUploaded * chunkSize;
if (beginningOfChunk + chunkSize > number_of_bytes_of_your_file) {
chunkSize = (int) number_of_bytes_of_your_file - beginningOfChunk;
}
request.setRequestProperty("Content-Length", String.format(Locale.ENGLISH, "%d", chunkSize));
request.setRequestProperty("Content-Range", "bytes " + beginningOfChunk + "-" + (beginningOfChunk + chunkSize - 1) + "/" + number_of_bytes_of_your_file);
byte[] buffer = new byte[(int) chunksize];
FileInputStream fileInputStream = new FileInputStream(yourFile);
fileInputStream.getChannel().position(beginningOfChunk);
fileInputStream.close();
OutputStream outputStream = request.getOutputStream();
outputStream.write(buffer);
outputStream.close();
request.connect();
chunksUploaded += 1;
// End of upload chunk section
Затем вы можете вызвать код фрагмента загрузки при повторении; в al oop, как функция; как хочешь. Поскольку это отдельный блок кода, вы можете называть его как хотите и, следовательно, реализовать какой-либо способ приостановки загрузки (через перерывы, засыпание, ожидание и т. Д. c).
Просто помните: вам понадобится чтобы сохранить URI сеанса для возобновления.
Обновление:
Похоже, что использование Drive V3 API напрямую для возобновляемых загрузок пока невозможно. Документация Java клиентской библиотеки ссылается на это при обсуждении того, когда использовать Drive: create
по сравнению с c библиотеками, не предназначенными для обслуживания:
... метод вставки API Drive поддерживает mediaUpload
, и вы можете использовать следующий код для загрузки файла:
code block
Вы также можете использовать функцию возобновляемой загрузки мультимедиа без специфичных для службы c сгенерированных библиотек.
Запрос функции:
Однако вы можете сообщить Google, что это функция, которая важна непосредственно для Drive API, а не требование использовать не-служебную спецификацию c библиотека. Google Issue Tracker - это место, где разработчики могут сообщать о проблемах и делать запросы функций для своих служб разработки. Страница для подачи запроса функции для Drive API: здесь .
Примечание о несоответствии: то, что называлось Drive.Files.Insert
в Drive API V2, было изменено на Drive.Files.Create
в Drive API V3.
Я знаю, что в целом это плохие новости, но надеюсь, что это будет полезно для вас!
Ссылки:
Вопросы по теме: