从 Java 中的 Google 云存储访问时损坏 TAR 文件错误

Corrupted TAR File Error Upon Access From Google Cloud Storage in Java

我正在 TAR 云存储中存储一个 TAR 文件。该文件可以通过 gsutil 成功下载并使用 macOS Archive Utility 在我的计算机中提取。但是,我实现的 Java 程序在访问文件时总是遇到 java.io.IOException: Corrupted TAR archive 。我尝试了几种方法,所有方法都在使用 org.apache.commons:commons-compress 库。你能告诉我如何解决这个问题或我可以尝试的东西吗?

以下是我尝试过的实现:

Blob blob = storage.get(BUCKET_NAME, FILE_PATH);
blob.downloadTo(Paths.get("filename.tar"));
String contentType = blob.getContentType(); // application/x-tar

InputStream is = Channels.newInputStream(blob.reader());
String mime = URLConnection.guessContentTypeFromStream(is); // null
TarArchiveInputStream ais = new TarArchiveInputStream(is);
ais.getNextEntry(); // raise java.io.IOException: Corrupted TAR archive

InputStream is2 = new ByteArrayInputStream(blob.getContent());
String mime2 = URLConnection.guessContentTypeFromStream(is2); // null
TarArchiveInputStream ais2 = new TarArchiveInputStream(is2);
ais2.getNextEntry(); // raise java.io.IOException: Corrupted TAR archive

InputStream is3 = new FileInputStream("filename.tar");
String mime3 = URLConnection.guessContentTypeFromStream(is3); // null
TarArchiveInputStream ais3 = new TarArchiveInputStream(is3);
ais3.getNextEntry(); // raise java.io.IOException: Corrupted TAR archive

TarFile file = new TarFile(blob.getContent()); // raise java.io.IOException: Corrupted TAR archive
TarFile tarFile = new TarFile(Paths.get("filename.tar")); // raise java.io.IOException: Corrupted TAR archive

补充:我尝试从 GCS 解析一个 JSON,它工作正常。

Blob blob = storage.get(BUCKET_NAME, FILE_PATH);
JSONTokener jt = new JSONTokener(Channels.newInputStream(blob.reader()));
JSONObject jo = new JSONObject(jt);

问题是你的 tar 被压缩了,它是一个 tgz 文件。

因此,您需要在处理 tar 内容时解压缩文件。

请考虑以下示例;注意使用内置的公共压缩 GzipCompressorInputStream class:

public static void main(String... args) {
  final File archiveFile = new File("latest.tar");
  try (
      FileInputStream in = new FileInputStream(archiveFile);
      GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in);
      TarArchiveInputStream tarIn = new TarArchiveInputStream(gzIn)
  ) {
    TarArchiveEntry tarEntry = tarIn.getNextTarEntry();
    while (tarEntry != null) {
      final File path = new File("/tmp/" + File.separator + tarEntry.getName());
      if (!path.getParentFile().exists()) {
        path.getParentFile().mkdirs();
      }

      if (!tarEntry.isDirectory()) {
        try (OutputStream out = new FileOutputStream(path)){
          IOUtils.copy(tarIn, out);
        }
      }
      tarEntry = tarIn.getNextTarEntry();
    }
  } catch (FileNotFoundException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
}