java google Drive api V3 分段和可断点上传

2024-03-14

我需要帮助编写大文件(> 5MB)的分段和可恢复上传,到目前为止,我只能启动分段上传,但我不知道当用户暂停或网络故障时如何恢复它。

我所说的“恢复”是指我不知道如何

1) 获取已上传到驱动器的总字节数

2) 如何在 Content-Range 标头中使用该值

3) 如何通过用户交互暂停此上传[executeAsInputStream() Maybe?]

这就是我到目前为止所做的。即使我要强行停止应用程序并重新启动它,我也需要代码从停止上传的位置恢复

   Drive service = GDrive.getService(); //Drive Specific Initialization Copied From QuickStart But with DriveScopes.FILES

   File fileMetadata = new File();
   fileMetadata.setName("Video.mp4"); //Video File
   fileMetadata.setMimeType("application/vnd.google-apps.video");

   java.io.File filePath = new java.io.File("E:\\large-file-60MB.mp4");//Large File Of 60 Mega Bytes
   FileContent mediaContent = new FileContent("video/mp4",filePath);

   Drive.Files.Create create=service.files().create(fileMetadata,mediaContent);

   MediaHttpUploader uploader=create.getMediaHttpUploader();
   uploader.setDirectUploadEnabled(false);                       //Use Resumable MultiPart Upload Protocol
   uploader.setChunkSize(2*MediaHttpUploader.MINIMUM_CHUNK_SIZE); //Chunks Of Bytes To Upload With Each Request

  // HttpHeaders headers=new HttpHeaders();
  // headers.put("Content-Range",?);          //This is not actual code which I used here but after reading the drive docs they talk about this header and I am not sure how or when to use it
  // uploader.setInitiationHeaders(headers);

   uploader.setProgressListener((uploading)->
   {
    switch (uploading.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("Progress="+uploading.getProgress());
      System.out.println("Bytes="+uploading.getNumBytesUploaded());
      break;
      case MEDIA_COMPLETE:System.out.println("Upload is complete!");
    }
   });

   create.execute(); 

虽然在一个答案中回答多个问题通常不适合 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 作为参数的便捷方法。

例如,insertDrive 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在你的情况下)并且应该很容易跟踪。

问题是,这实际上并不需要。您可以根据文档(强调我自己的文档)使用通配符来指示文件的当前位置未知:

如果上传请求在响应之前终止,或者收到 5​​03 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请求给/uploadDrive 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 UPLOADGUI 中的按钮,用于切换是否继续上传的下一部分。

要记住的是,上传文件内容时,发出的请求必须通过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.InsertDrive 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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java google Drive api V3 分段和可断点上传 的相关文章

  • 如何将变量的全部内容发送/导出到文本文件/xml 文件/剪贴板?

    我想将实例的内容 最好以树形形式 发送给某人 打印屏幕是不行的 因为类太复杂了 您需要将输出转回实例吗 在这种情况下 其他答案都是正确的 如果您只想手动检查实例的内容 理想情况下您的类都将实现toString 你可以将其重定向到一个文件 如
  • 如何从 Play WSClient 的字符串创建 WSResponse 对象

    文档 https www playframework com documentation 2 4 x JavaTestingWebServiceClients Mock the web service建议使用模拟Web服务测试基于WSCli
  • 如何在Java中优雅地处理SIGKILL信号

    当程序收到终止信号时如何处理清理 例如 我连接到一个应用程序 希望任何第三方应用程序 我的应用程序 发送finish注销时的命令 发送该信息最好说什么finish当我的应用程序被破坏时的命令kill 9 编辑1 kill 9无法被捕获 谢谢
  • JavaFX 2.0 FXML 子窗口

    经过多次搜索我发现了这个问题如何创建 javafx 2 0 应用程序 MDI https stackoverflow com questions 10915388 how to create a javafx 2 0 application
  • 在 Java 中从 SOAPMessage 获取原始 XML

    我已经在 J AX WS 中设置了 SOAP WebServiceProvider 但我无法弄清楚如何从 SOAPMessage 或任何 Node 对象获取原始 XML 下面是我现在获得的代码示例 以及我试图获取 XML 的位置 WebSe
  • javax.persistence.RollbackException:提交事务时出错],根本原因是 java.lang.StackOverflowError:null

    我有一个使用 Spring Data REST 框架的 Spring Boot API 从 spring boot starter parent 2 1 0 RELEASE 继承的依赖项 我正在尝试执行 PUT 或 PATCH 请求来更新实
  • 检查 IPv4 地址是否在私有范围内

    在 Python 中 使用 IPy 模块您可以执行以下操作 gt gt gt ip iptype PRIVATE 有没有一个库或简单的方法可以在 Java 中执行相同的操作 似乎不完全是但是InetAddress有一些 isXX 方法 例如
  • JTextField 和 JTextArea

    JTextField 和 JTextArea 有什么不同 是否可以在一个班级中使用这两个班级 总之 JTextField 是单行文本字段 而 JTextArea 可以跨越多行 文档中清楚地解释了这些差异 文本区 http docs orac
  • 使用 JSch 分别为各个提示提供输入

    问题是 SSH 连接需要在常规登录后提供另一个用户 ID 和密码信息 我正在使用 JSch 连接到远程服务器 它接受以下形式的输入InputStream 和这个InputStream只能通过一次 由于会话是交互式的 这会导致问题 我尝试将输
  • java中的单链表和双向链表?

    在java中 哪个集合接口可以有效地实现单链表和双向链表 请问代码示例吗 毫不奇怪 实现双向链表的正确接口是 LinkedList 看Java文档 http docs oracle com javase 8 docs api java ut
  • OpenNLP 与斯坦福 CoreNLP

    我一直在对这两个包进行一些比较 但不确定该往哪个方向走 我简单地寻找的是 命名实体识别 人 地点 组织等 性别识别 一个不错的训练 API 据我所知 OpenNLP 和斯坦福 CoreNLP 提供了非常相似的功能 然而 Stanford C
  • 使用 JAX-WS 的 WebLogic 中没有模式导入的单个 WSDL

    如何使用 JAX WS 配置由 WebLogic 10 3 6 生成的 Web 服务 以将对象架构包含在单个 WSDL 文件声明 而不是导入声明 中 示例代码 界面 import javax ejb Local Local public i
  • 在 Java 中创建 T 的新实例

    在C 中 我们可以定义一个泛型class A
  • LocalDate 减去 period 得到错误的结果

    LocalDate减去一个Period 如 28年1个月27天 得到错误的结果 但减去一个Period 只有天单位 如 10282 天 得到正确的结果 有什么需要注意的吗 public static void main String arg
  • java.lang.Object的hashCode具体使用的算法是什么

    中使用的算法是什么JVM实施java lang Object的隐含的hashCode 方法 OpenJDK or Oracle JDK答案中首选 它依赖于实现 并且在很大程度上 该算法是entirely取决于实施 只要它是一致的 但是 根据
  • Java 中的 ExecuteUpdate sql 语句不起作用

    我正在学习如何将 SQL 与 Java 结合使用 我已成功安装 JDBC 驱动程序 并且能够从数据库读取记录并将其打印在屏幕上 我的问题发生在尝试执行更新或插入语句时 没有任何反应 这是我的代码 问题所在的方法 public static
  • 查找数组中的组合

    我在java中有一个像这样的二维数组 transmission communication tv television approach memorycode methodact 我需要获得所有组合 例如 transmission appr
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • Java 中的微分方程

    我正在尝试用java创建一个简单的SIR流行病模型模拟程序 基本上 SIR 由三个微分方程组定义 S t l t S t I t l t S t g t I t R t g t I t S 易感人群 I 感染人群 R 康复人群 l t c
  • 使用 AmazonSNSClient 发送短信时的授权

    aws 官方文档如何发送短信 http docs aws amazon com sns latest dg sms publish to phone html使用 java 中的 aws SDK 非常简单 但是 当发送如底部示例所示的消息时

随机推荐

  • 如何创建与列相关的大小的 Pyspark 窗口函数

    当我尝试使用 pyspark 中的窗口函数对与列相关的前行数进行累积值时 出现意外错误 重现我遇到的错误的最小工作示例 MWE 如下 from pyspark sql import Window import pandas as pd df
  • 在Python中处理键盘事件

    如何在 python 中处理键盘事件 更确切地说 我需要为我的命令行应用程序管理键盘箭头和其他一些键 是否有一个模块可以实现此目的 或者我需要使用例如 if get key mykey do Something 它是伪代码 来逐个处理键 我
  • 使用 Django 在 Heroku 上提供根级静态文件?

    我需要在 Heroku 上提供几个根级静态文件 例如 domain com favicon ico 以下是当前的文件列表 favicon ico crossdomain xml sitemap xml robots txt humans t
  • 检测服务中的屏幕方向变化[重复]

    这个问题在这里已经有答案了 一个非常简单直接的问题 服务是否可以检测屏幕方向的变化 如果是这样 怎么办 此链接将回答您的问题 如何使用服务来监控 Android 中的方向变化 https stackoverflow com question
  • MUI 网格禁用 GridToolBar 中的导出按钮

    如何在 MUI 中禁用 覆盖 XGrid GridToolbar 的导出按钮 对于将来重新讨论这个问题的任何人 我发现 DataGrid 组件上的组件组件属性允许您传入具有 csvOptions 的对象来禁用导出按钮
  • 为什么从 INSTALLED_APPS 中删除“django.contrib.sites”可以修复我突然出现的“DoesNotExist at /admin/”错误?

    昨天我设置了一个新的 Django 应用程序 当我停止工作时 管理员仍然可以正常工作 今天早上我运行服务器 我看到这个错误页面 DoesNotExist at admin Site matching query does not exist
  • 在 mongodb 中按 $type 编号查找

    我有以下文件 gt db people insert name Bob gt db people insert name 42 如果我需要按类型查找String我可以用 gt db people find name type 2 Where
  • 运行时服务不再注入 DNX 控制台应用程序 (RC1)

    我曾经能够注入运行时服务 例如IApplicationEnvironment到构造函数中PogramDNX 控制台应用程序的类 但是 使用最新的 RC1 CI 版本 服务不再被注入 public Program IApplicationEn
  • 无法将 MySQL.DateTime 转换为具有 0000-00-00 00:00:00 值的 System.DateTime

    我正在开发一个 C 项目 但遇到了一个问题 该程序允许用户连接到 MySQL 数据库并从每个选定的表中检索信息并将数据写入文件 问题是因为我不知道架构会是什么样子或者它会包含什么值 如果时间戳列包含日期 0000 00 00 00 00 0
  • Python-将稀疏矩阵行与非稀疏向量乘以索引

    我当前的软件项目涉及使用 python 实现求解线性系统的数值方法 所谓的SOR 方法 它基本上是这样工作的 给定一个线性系统 ax1 bx2 cx3 b1 dx1 ex2 fx3 b2 gx1 hx2 ix3 b3 重新排列方程为 x1
  • 如何统计QEMU从运行开始到结束执行的客户指令数量?

    我想对 QEMU 每秒的客户指令进行基准测试 以将其与其他模拟器进行比较 如何获取访客指令数 我对用户模式和完整系统模式都感兴趣 我现在唯一的解决方案是使用简单的跟踪记录所有指令exec tb or d in asm 如何使用 QEMU 的
  • 为什么定义函数之前需要使用分号? [复制]

    这个问题在这里已经有答案了 我见过一些奇怪的 在一些 jQuery 插件源代码的函数开头 如下所示 function 有人可以解释为什么他们需要使用 在这种情况下 当文件中当前存在的代码不包含新代码时 此分号将帮助您正确地将新代码连接到文件
  • 长按后移动事件

    在我的 GestureDetector 中调用长按后 如何监听移动事件 当用户长按时 他启动选择模式 并且可以将一个正方形拖到屏幕中 但我注意到 在使用 LongPress 后 不会调用 onScroll 尝试解决这个问题一段时间 目前的解
  • 序言排列函数

    我是 Prolog 的新手 我知道排列的递归函数 即 per per L X P del X L L1 per L1 P 我想知道当我们收到时这个函数在最后一次迭代中的逻辑树per 它返回哪个元素 Sonia 您还没有给我们 del 谓词
  • .NET 异常类型的 _xcode 字段是什么?

    在我的单元测试中 我需要对两个对象执行深度相等测试 这两个对象应该是相同的 在测试过程中 我发现系统类型中一些有趣的字段破坏了我的代码 Exception xcode是最新的 以下是有关该领域的一些事实 它被初始化为 532459699在所
  • `__CPROVER_fence()` 参数

    我看到类似的代码 CPROVER fence RRfence RWfence 正在像这样的项目中使用Linux RCU 测试 https git kernel org pub scm linux kernel git torvalds li
  • 内存中集成测试和环境变量——.net core

    我们可以执行一个测试服务器来进行集成测试 就像是 这个问题 https stackoverflow com questions 29968788 how do i run in memory integration tests using
  • Flutter返回首页

    我制作了一个应用程序 其中包含相当多的路由 可以相互推送多个全屏对话框 但我想从一个对话框中关闭所有对话框并返回主页 我怎样才能做到这一点 我不想再次推送主页 因为这样我的导航历史记录中仍然有所有这些对话框 是pushReplacement
  • 低级控制台输入和重定向

    我正在尝试将命令发送到a的输入cmd exe使用低级读 写控制台功能的应用程序 我使用以下命令阅读文本 抓取 没有任何问题ReadConsole and WriteConsole 连接到进程控制台后的功能 但我还没有弄清楚如何编写 dir
  • java google Drive api V3 分段和可断点上传

    我需要帮助编写大文件 gt 5MB 的分段和可恢复上传 到目前为止 我只能启动分段上传 但我不知道当用户暂停或网络故障时如何恢复它 我所说的 恢复 是指我不知道如何 1 获取已上传到驱动器的总字节数 2 如何在 Content Range