虽然在一个答案中回答多个问题通常不适合 Stack Overflow,但似乎这些问题都是紧密相连的,因此将概述可恢复上传,并在此过程中尝试解决您的三点:
- 如何获取已上传到云端硬盘的总字节数
- 如何使用 Content-Range 标头中的值
- 如何暂停可续传上传
来自谷歌的文档直接和可恢复媒体上传 https://developers.google.com/api-client-library/java/google-api-java-client/media-upload关于 Java API 客户端库文档:
实施细节
主要兴趣类别是媒体Http上传器 https://googleapis.dev/java/google-api-client/latest/com/google/api/client/googleapis/media/MediaHttpUploader.html and MediaHttpProgressListener https://googleapis.dev/java/google-api-client/latest/com/google/api/client/googleapis/media/MediaHttpUploaderProgressListener.html.
如果特定于服务的生成库中的方法包含mediaUpload
中的参数发现文件 https://developers.google.com/discovery/v1/using,然后为这些方法创建一个以 InputStreamContent 作为参数的便捷方法。
例如,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 之类的内容,因此,如果您希望能够执行此操作,则需要遵循记录的可续传上传启动步骤here https://developers.google.com/drive/api/v3/manage-uploads#send_the_initial_request。但这都是手动完成的,而不是直接使用 Google Drive API 客户端库。
要回答第一点,如何存储已上传的字节数取决于您。而不是思考“云端硬盘上已有多少内容”, think “我已经上传了多少?”.
如果您愿意,您可以将其存储为本地变量,因为它将是块大小的倍数(2 * MediaHttpUploader.MINIMUM_CHUNK_SIZE
在你的情况下)并且应该很容易跟踪。
问题是,这实际上并不需要。您可以根据文档(强调我自己的文档)使用通配符来指示文件的当前位置未知:
如果上传请求在响应之前终止,或者收到 503 Service Unavailable 响应,则需要恢复中断的上传。
要请求上传状态,请创建一个空的PUT
请求可恢复会话 URI。
Add a Content-Range
标头指示文件中的当前位置未知。例如,设置Content-Range
to */2000000
如果您的文件总长度为 2,000,000 字节。如果您不知道文件的完整大小,请设置Content-Range
to */*
.
如果您确实想跟踪字节,您可以在您的Content-Range
标头为
Content-Range: bytes_so_far/total_bytes
Steps:
要初始化断点续传,您需要创建一个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 将在一周后过期。 https://developers.google.com/drive/api/v3/manage-uploads#send_the_initial_request
如何暂停可续传上传:
实际上这取决于您希望如何实现。例如,你可以打破一个循环,或者有一个巨大的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
然后您可以重复调用上传块代码;在循环中,作为函数;你喜欢怎样。由于它是一个独特的代码块,您可以根据需要调用它,从而实现某种暂停上传的方法(通过中断、睡眠、等待等)。
请记住:您需要保存会话 URI 才能恢复。
Update:
直接使用 Drive V3 API 来进行断点续传似乎还不太可能。这Java 客户端库文档 https://developers.google.com/api-client-library/java/google-api-java-client/media-upload#implementation在讨论何时使用时提到了这一点Drive: create
与非特定于服务的库相比:
...Drive API的插入方法支持mediaUpload
,您可以使用以下代码上传文件:
代码块
You can also use the resumable media upload feature without the service-specific generated libraries.
功能要求:
不过,您可以让 Google 知道这是一项对 Drive API 直接重要的功能,而不是使用非服务特定库的要求。 Google 的问题跟踪器是开发人员报告问题并为其开发服务提出功能请求的地方。提交 Drive API 功能请求的页面是.
差异说明:叫什么Drive.Files.Insert
Drive API V2 中更改为Drive.Files.Create
在驱动器 API V3 中。
参考:
- Java 快速入门 |谷歌云端硬盘 API |谷歌开发者 https://developers.google.com/resources/api-libraries/documentation/drive/v3/java/latest
- Drive.Files.Create(驱动器 API v3(修订版 197)1.25.0) https://developers.google.com/resources/api-libraries/documentation/drive/v3/java/latest/
- 创建并填充文件夹 |谷歌云端硬盘 API |谷歌开发者 https://developers.google.com/drive/api/v3/folder
- 上传文件数据 |谷歌云端硬盘 API |谷歌开发者 https://developers.google.com/drive/api/v3/manage-uploads#java_1
- 文件:创建|谷歌云端硬盘 API |谷歌开发者 https://developers.google.com/drive/api/v3/reference/files/create
- 直接和可恢复媒体上传 | Java API 客户端库 https://developers.google.com/api-client-library/java/google-api-java-client/media-upload#implementation
相关问题:
- Google Drive api Java - 我的大型分段上传完成了吗? https://stackoverflow.com/questions/59794970/
- 在 Google Drive Java API 中设置 uploadType https://stackoverflow.com/questions/19360990/
- Drive Rest API V3 中的断点续传上传 https://stackoverflow.com/questions/39887303/
- Google Drive API - Drive.Files 类没有 insert() 方法 https://stackoverflow.com/questions/48085032