我正在尝试使用文件上传 API,该 API 需要以字节大小的块上传文件,该字节大小是从先前的 API 调用中指定的。所以....例如,如果文件很小,它会说以 1MB(以字节为单位)的块上传它,但它很大,它可能会说以 10MB 块上传它,如果它真的很小,它可能会简单地返回给我文件大小表明我应该一次全部上传。关键是我不提前知道。它还需要我将块的顺序指定为查询参数,因此我需要在循环浏览文件块时跟踪我尝试上传的块号。
无论如何,我在我的项目中使用 Retrofit / OkHttp 并认为这对 Okio 来说应该是一个很好的用例。这就是我目前所拥有的,它似乎有效。但是我是 Okio 的新手,不知道我是否遗漏了一些明显的东西,或者这是否可以以更好的方式完成。
private void chunkedUpload(int offset, int chunkSize, int blockNumber, @Nonnull CompletableFuture<Foo> future) {
File file = ...
String url = ...
try (final BufferedSource bufferedSource = Okio.buffer(Okio.source(file))) {
bufferedSource.skip(offset);
final Buffer buffer = new Buffer();
final boolean isFinal = !bufferedSource.request(chunkSize);
bufferedSource.read(buffer, chunkSize);
final RequestBody requestFile = RequestBody.create(buffer.readByteArray(), null);
upload(offset, chunkSize, url, requestFile, blockNumber, future, isFinal);
} catch (IOException e) {
future.completeExceptionally(e);
}
}
private void upload(int offset, int chunkSize, @Nonnull String url, @Nonnull RequestBody requestFile, int blockNumber, @Nonnull CompletableFuture<Foo> future, boolean isFinal) {
fileUloadService.uploadApp(url + "&block_number=" + blockNumber, requestFile)
.whenComplete((responseBody, throwable) -> {
if (throwable != null) {
future.completeExceptionally(throwable);
} else {
if (isFinal) {
future.complete();
return;
}
chunkedUpload(offset + chunkSize, chunkSize, blockNumber + 1, future);
}
});
}
您可以看到我正在绑定上传一个块,等待成功响应(来自 Java 8 ),然后使用更新的和再次CompletableFuture
调用该方法。就像我说的,它有效,但我是 Okio 的新手,想知道我是否遗漏了一些明显的东西?chunkedUpload
offset
blockNumber
为什么我想使用 Okio 很大程度上是因为我要上传的文件通常在 30MB 到 1GB 之间,所以不要想一次将所有这些文件加载到内存中 :)。