当前位置: 首页 > 知识库问答 >
问题:

如何通过Java API分块上传到谷歌云存储?

澹台臻
2023-03-14

我正在尝试,在一个Java的环境中,将日志文件以块的形式写入Google云存储。我有一个解析原始日志文件并生成JSON行的进程;我将JSON行存储在缓冲区中,每次缓冲区达到5MGB左右时,我都希望写入GCS中的同一文件,直到原始raw源代码被完全解析。我有一个类似的设置写入AWS3。由于内存问题,大块写作是完成的。

我设法向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();
}

不幸的是,我一直无法弄清楚如何以块的形式写到GCS。谷歌的文档似乎建议了两种方法。一个涉及“可恢复的”插入请求:https://cloud.google.com/storage/docs/jsonapi/v1/how-tos/upload

另一种方法涉及“compose”请求:https://cloud.google.com/storage/docs/jsonapi/v1/objects/compose

我一直试图得到一个“可恢复的”上传设置,但我不能使它工作。

有什么想法吗?我的具体问题是:

  • 什么是以块形式上载到GCS的优雅和/或合适的方式?
  • 有没有人知道如何在Java通过插入请求设置可恢复的上载到GCS?那能行吗?

共有1个答案

鲁烨
2023-03-14

让它起作用了-这是个麻烦。我的问题的答案如下:

  • “可恢复”上载在Java很管用,是一种优雅的方式,也许是将文件分块上载到GCS的首选方式(我不是专家,所以我不确定)。
  • 可以在Java设置“可恢复”上载,如下所述。

最后我有两种方法--一种用于启动上传,另一种用于发送块。

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;

上面的代码可能有一些bug,但它确实成功地将一个文件块写入GCS。

我还设法通过一个不同的库和“compose”请求来完成任务。但“可恢复”的方式似乎更合适。

干杯祝你好运。

 类似资料:
  • 我正在尝试上传文件到谷歌存储在多块但签名的URL。 以下是我正在执行的步骤: 使用node.js创建可恢复的上载URL 示例URL: 使用这些标头: HTTPS响应: 使用这些标头: HTTPS响应:包含数据: 根据文档,上述响应应该是,而不是。 我对这些API调用做错了什么?

  • 我正在尝试使用谷歌云存储JSON API将图像上传到谷歌云存储桶中。文件正在上载,但没有显示任何内容。 我正在通过以下方式上载图像:- 图像1 看图片1,文件上传成功。但当我点击它查看它时,它显示如图2所示。 图像2

  • 我应该做什么才能成功上传图片?任何帮助都将不胜感激。 非常感谢。

  • 我目前面临的问题与谷歌云存储, 我能够下载对象上传到谷歌云存储,但当天晚些时候,我开始得到的错误,因为"这个网站无法到达" 我在c#中以编程方式创建了一个bucket,代码如下: 因此,创建存储桶的设置如下: 默认存储类别:多地区 位置:美国(美国多个地区) 公共访问:每个对象 生命周期:无 访问控制模型:存储桶策略

  • 追踪下面。 相关的Python片段: 最终触发(从ssl库): 溢出错误:字符串长度超过2147483647字节 我想我缺少一些特殊的配置选项? 这可能与这名1.5岁的年轻人有关,显然他还没有解决问题:https://github.com/googledatalab/datalab/issues/784. 谢谢你的帮助! 完整跟踪: [File”/usr/src/app/gcloud/downlo

  • 我想按照官方文档中提供的示例将一个文件上传到Google云存储 然而,我得到了一个错误: 线程“main”com.google.cloud.storage.StorageException中的异常:获取服务帐户的访问令牌时出错:400个错误请求{“错误”:“无效的授予”、“错误描述”:“无效的JWT:令牌必须是短期令牌(60分钟)并且在合理的时间范围内。请检查JWT声明中的iat和exp值。”位于