我正在尝试在 Java 环境中将日志文件分块写入 Google Cloud Storage。我有一个进程可以解析原始日志文件并生成 JSON 行;我将 JSON 行存储在缓冲区中,每次缓冲区达到 5mgb 左右时,我想写入 GCS 中的同一个文件,直到完全解析原始原始源。我有一个写入 AWS S3 的类似设置。由于内存问题,分块写入。
我设法将文件写入GCS,如下所示(gcsService是配置了身份验证等的存储对象):
private void uploadStream(String path, String name, String contentType, InputStream stream, String bucketName) throws IOException, GeneralSecurityException {
InputStreamContent contentStream = new InputStreamContent(contentType, stream);
StorageObject objectMetadata = new StorageObject()
.setName(path+"/"+name)
.setAcl(Arrays.asList(new ObjectAccessControl().setEntity("allUsers").setRole("READER")));
Storage.Objects.Insert insertRequest = gcsService.objects()
.insert(bucketName, objectMetadata, contentStream);
insertRequest.execute();
}
不幸的是,我一直无法弄清楚如何以 block 的形式写入 GCS。谷歌的文档似乎提出了两种方法。其中之一涉及“可恢复”插入请求: https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload
另一种方法涉及“撰写”请求: https://cloud.google.com/storage/docs/json_api/v1/objects/compose
我一直在尝试设置“可恢复”上传,但无法使其正常工作。
有什么想法吗?我的具体问题是:
- 将 block 上传到 GCS 的优雅和/或适当的方式是什么?
- 有人知道如何通过 Java 中的插入请求设置到 GCS 的可断点续传上传吗?这完全可以做到吗?
最佳答案
让它工作 - 这很麻烦。作为记录,我的问题的答案是:
- “可恢复”上传在 Java 中工作,对于将文件分块上传到 GCS 来说,这是一种优雅的方式,也许是首选方式(我不是专家,所以我不确定)。
- 可以按照如下所述在 Java 中设置“可断点续传”上传。
我最终有两种方法 - 一种用于启动上传,另一种用于发送 block 。
private String initiateResumableUpload() throws IOException {
String URI = "https://storage.googleapis.com/" + bucket + "/" + path;
GenericUrl url = new GenericUrl(URI);
HttpRequest req = requestFactory.buildPostRequest(url, new ByteArrayContent("text/plain", new byte[0]));
HttpHeaders headers = new HttpHeaders();
headers.set("x-goog-resumable", "start");
headers.setContentLength((long) 0);
headers.setContentType("text/plain");
req.setHeaders(headers);
req.setReadTimeout((int) DEFAULT_TIMEOUT);
req.setResponseHeaders(headers);
HttpResponse resp;
try {
resp = req.execute();
} catch (IOException e) {
throw e;
}
if (resp.getStatusCode() == 201) {
String location = resp.getHeaders().getLocation();
return location;
} else {
throw new IOException();
}
}
requestFactory 应该知道您适当生成的凭据。
private void writeChunk(final boolean isFinalChunk) throws HttpResponseException, IOException {
System.out.println("Writing chunk number " + Integer.toString(chunkCount) + ".");
try (InputStream inputStream = new ByteBufInputStream(buffer)) {
int length = Math.min(buffer.readableBytes(), DEFAULT_UPLOAD_CHUNK_SIZE);
HttpContent contentsend = new InputStreamContent("text/plain", inputStream);
String URI = location;
GenericUrl url = new GenericUrl(URI);
HttpRequest req = requestFactory.buildPutRequest(url, contentsend);
int offset = chunkCount*DEFAULT_UPLOAD_CHUNK_SIZE;
long limit = offset + length;
HttpHeaders headers = new HttpHeaders();
headers.setContentLength((long) length);
headers.setContentRange("bytes " + (length == 0 ? "*" : offset + "-" + (limit - 1)) + (isFinalChunk ? "/" + limit : "/*"));
req.setHeaders(headers);
req.setReadTimeout((int) DEFAULT_TIMEOUT);
try {
req.execute();
}
catch (HttpResponseException e) {
if(e.getMessage().equals("308 Resume Incomplete"))
{
++chunkCount;
}
else
{
throw e;
}
}
catch (Exception e) {
throw e;
}
}
}
我的缓冲区是 io.netty.buffer.ByteBuf。
我的 GCS 相关导入是:
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.ByteArrayContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpContent;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpResponseException;
import com.google.api.client.http.HttpTransport;
上面的代码可能存在一些错误,但它确实成功地将文件分块写入GCS。
我还设法通过不同的库和“撰写”请求来完成任务。但“可恢复”的方式似乎更合适。
干杯,祝你好运。
关于java - 如何通过 Java API 将 block 上传到 Google Cloud Storage?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36610398/