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

来自Google云存储的流文件

柏高洁
2023-03-14
@Override
public void write(OutputStream outputStream) throws IOException {
    try {
        LOG.info(path);
        InputStream stream = new ByteArrayInputStream(GoogleJsonKey.JSON_KEY.getBytes(StandardCharsets.UTF_8));
        StorageOptions options = StorageOptions.newBuilder()
                .setProjectId(PROJECT_ID)
                .setCredentials(GoogleCredentials.fromStream(stream)).build();
        Storage storage = options.getService();
        final CountingOutputStream countingOutputStream = new CountingOutputStream(outputStream);
        byte[] read = storage.readAllBytes(BlobId.of(BUCKET, path));
        countingOutputStream.write(read);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        outputStream.close();
    }
}

这是可行的,但这里的问题是,在流回此方法的客户端之前,它必须首先缓冲所有字节。这会导致很多延迟,尤其是当存储在GCS中的文件很大时。

是否有一种方法可以从GCS获取文件并将其直接流到OutputStream,这里的OutputStream是针对servlet的。

共有1个答案

公风史
2023-03-14

为了澄清一下,您需要outputstream还是inputstream?一种方法是,存储在Google Cloud Storage中的数据作为一个文件对象,您有一个InputStream来读取该文件。如果有用,请继续阅读。

Storage API中没有提供InputStreamOutputStream的现有方法。但是云存储客户端库中有两个API,它们公开了一个ReadChannel对象,该对象是从ReadableByteChannel(来自java NIO API)扩展而来的。

ReadChannel reader(String bucket, String blob, BlobSourceOption... options);
ReadChannel reader(BlobId blob, BlobSourceOption... options);

使用以下内容的一个简单示例(摘自StoragesNippets.java):

/**
   * Example of reading a blob's content through a reader.
   */
  // [TARGET reader(String, String, BlobSourceOption...)]
  // [VARIABLE "my_unique_bucket"]
  // [VARIABLE "my_blob_name"]
  public void readerFromStrings(String bucketName, String blobName) throws IOException {
    // [START readerFromStrings]
    try (ReadChannel reader = storage.reader(bucketName, blobName)) {
      ByteBuffer bytes = ByteBuffer.allocate(64 * 1024);
      while (reader.read(bytes) > 0) {
        bytes.flip();
        // do something with bytes
        bytes.clear();
      }
    }
    // [END readerFromStrings]
  }

还可以使用NewinPutStream()方法将InputStream包装到ReadableByteChannel上。

公共静态InputStream newInputStream(ReadableByteChannel ch)

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

import com.google.cloud.ReadChannel;
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

/**
 * An example which reads the contents of the specified object/blob from GCS
 * and prints the contents to STDOUT.
 *
 * Run it as PROGRAM_NAME <BUCKET_NAME> <BLOB_PATH>
 */
public class ReadObjectSample {
  private static final int BUFFER_SIZE = 64 * 1024;

  public static void main(String[] args) throws IOException {
    // Instantiates a Storage client
    Storage storage = StorageOptions.getDefaultInstance().getService();

    // The name for the GCS bucket
    String bucketName = args[0];
    // The path of the blob (i.e. GCS object) within the GCS bucket.
    String blobPath = args[1];

    printBlob(storage, bucketName, blobPath);
  }

  // Reads from the specified blob present in the GCS bucket and prints the contents to STDOUT.
  private static void printBlob(Storage storage, String bucketName, String blobPath) throws IOException {
    try (ReadChannel reader = storage.reader(bucketName, blobPath)) {
      WritableByteChannel outChannel = Channels.newChannel(System.out);
      ByteBuffer bytes = ByteBuffer.allocate(BUFFER_SIZE);
      while (reader.read(bytes) > 0) {
        bytes.flip();
        outChannel.write(bytes);
        bytes.clear();
      }
    }
  }
}
 类似资料:
  • 我试图将一个用编写的函数迁移到 实时解压缩并逐行读取 对每一行执行一些光转换 将未压缩的输出(一次一行或块)写入GCS 输出是>2GB,但略小于3GB,所以它适合。 null AFAIC,我将坚持,因为输出可以放入内存--就目前而言--但是多部分上传是以最少的内存支持任何输出大小的方法。 想法还是替代方案?

  • 我正在尝试使用DataFlow(Java)将数据从云存储插入到Big Query中。我可以批量上传数据;但是,我想要设置一个流式上传代替。因此,当新对象添加到我的bucket时,它们将被推送到BigQuery。 我已经将PipelineOptions设置为流,并且在GCP控制台UI中显示dataflow管道是流类型的。bucket中的初始文件/对象集被推送到BigQuery。 但是当我向桶中添加新

  • 如果在GCS上存储了一个。txt文件,该文件包含将用作一部分的单词列表,可以在apache beam管道中动态访问该列表吗?我知道我可以将这个列表定义为管道中的全局变量,但我不确定如何将整个文件读入列表,以及是否有任何beam技巧来实现这一点。有什么建议吗?这是我当前的实现,这是不工作的… 我得到以下错误“TypeError:类型'_invalidunpickledpCollection'的参数不

  • 我的网站文件托管在Google Cloud Storage,每次我更新一个文件(比如。png或。xml)时,我总是要等一段时间才能看到新文件出现在我的页面上。 有没有办法覆盖单个对象的默认缓存设置(max-age=3600)?尝试用“no store”、“no cache”、“max-age=0”编辑“cache-control”元数据,但它们似乎都不起作用,仍然在响应头中获得“cache-con

  • 我想从JPA存储库中创建一个流。目标是将来自回购的实体(可能超过一百万)映射到其他实体,这些实体将依次存储在另一个回购中。 到目前为止,我构建了一个收集器,它将收集给定数量(例如1000)实体,然后将其存储到目标存储库中。这将在并行流中工作。我现在需要的是一种从源存储库中提取实体并在需要时将它们馈送到流中的好方法。 到目前为止,最有希望的是实现供应商(http://docs.oracle.com/