You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Tika检测Content-Type上传GCS文件损坏,手动设置则正常

问题原因分析

核心问题出在输入流的状态被修改:Apache Tika的detect(InputStream)方法会读取流中的内容来判断文件类型,这会导致流的指针移动到流的末尾。当后续调用Google Cloud Storage SDK的bucket.create方法时,输入流已经没有可读数据,实际上传的是不完整或空的文件内容,因此下载后文件损坏。

虽然控制台显示的文件大小、Content-Type等元数据看似正确,但这是因为SDK可能提前获取了流的长度(比如针对文件流时读取文件系统的大小),但实际传输的内容已经缺失。

解决方案

针对这个问题,有几种可行的修复方式,根据你的场景选择:

1. 包装流并重置位置(适合大多数流场景)

如果输入流支持标记/重置(或通过包装使其支持),可以在检测类型后将流重置到初始位置:

Tika tika = new Tika();
// 用BufferedInputStream包装原始流,使其支持mark/reset
InputStream bufferedStream = new BufferedInputStream(inputStream);
// 标记流的初始位置,参数设为流的最大可能长度
bufferedStream.mark(Integer.MAX_VALUE);

String contentType = tika.detect(bufferedStream);
System.out.println(contentType); //"application/pdf"

// 将流重置到标记的初始位置
bufferedStream.reset();

if("application/pdf".equals(contentType)) {
     return bucket.create(Utilities.formatDirectoryName(directory) + name, bufferedStream, contentType);
} else {
     System.out.println("INVALID TYPE");
     return null;
}

2. 将流读取为字节数组(适合小文件场景)

如果文件体积不大,可以先将流内容读取到字节数组中,再分别用于Tika检测和上传:

Tika tika = new Tika();
// 读取流内容到字节数组(可使用Apache Commons IO的IOUtils,或自行实现读取逻辑)
byte[] fileBytes = IOUtils.toByteArray(inputStream);

String contentType = tika.detect(fileBytes);
System.out.println(contentType); //"application/pdf"

// 用字节数组重新生成输入流用于上传
if("application/pdf".equals(contentType)) {
     return bucket.create(Utilities.formatDirectoryName(directory) + name, new ByteArrayInputStream(fileBytes), contentType);
} else {
     System.out.println("INVALID TYPE");
     return null;
}

3. 直接用文件路径/File对象检测(如果有本地文件)

如果你的原始文件存储在本地磁盘,可以直接使用Tika的detect(File)重载方法,避免操作输入流:

Tika tika = new Tika();
File localFile = new File("你的本地文件路径");
String contentType = tika.detect(localFile);
System.out.println(contentType); //"application/pdf"

// 重新打开文件流用于上传
try (InputStream fileStream = new FileInputStream(localFile)) {
    if("application/pdf".equals(contentType)) {
         return bucket.create(Utilities.formatDirectoryName(directory) + name, fileStream, contentType);
    } else {
         System.out.println("INVALID TYPE");
         return null;
    }
} catch (IOException e) {
    // 处理异常
    e.printStackTrace();
    return null;
}

内容的提问来源于stack exchange,提问作者Raymond Holguin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:35:04