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

无法通过Spring Boot REST API上传对象至GCP Storage的问题

Spring Boot 上传文件到GCP Storage报403(账户未启用计费)但实际已开启计费的问题

问题背景

使用Spring Boot REST API上传文件至GCP Storage时触发403错误,提示存储桶对应的账户未启用计费,但已确认该账户计费功能处于开启状态。此外,用Express和Python Flask的REST API可正常上传至同一存储桶,且此前用相同Spring Boot代码实现过该功能。

错误信息

com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
POST https://storage.googleapis.com/upload/storage/v1/b/pdf-split-ingestion/o?projection=full&uploadType=multipart

{
"code" : 403,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "The account for bucket \"pdf-split-ingestion\" has not enabled billing.",
"reason" : "accountDisabled"
} ],
"message" : "The account for bucket \"pdf-split-ingestion\" has not enabled billing."
}

相关代码

@RestController
@RequestMapping("")
public class Controller {

@Autowired
private Repo repo;

String projectId = "spring-b-357511";
String bucketName = "pdf-split-ingestion";
Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
@PostMapping("/upload-file")
public ResponseEntity<String> uploadFile1(@RequestParam("file")MultipartFile file){
    String Name = file.getOriginalFilename();
    if (file.isEmpty()){
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("File is missing in request");
    }

    try{
        InputStream is = file.getInputStream();
        byte data[] = new byte[is.available()];
        is.read(data);
        BlobId blobId = BlobId.of(bucketName, file.getOriginalFilename());
        BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
        storage.create(blobInfo,data);

    } catch (IOException e) {
        e.printStackTrace();
    }
    Model response = new Model();
    repo.save(response);
    return ResponseEntity.ok("File uploaded Successfully");
}

解决方案

  • 验证应用使用的身份凭据
    你的代码未显式指定服务账号密钥,默认使用运行环境的默认凭据:

    • 本地运行:检查gcloud auth application-default login关联的账号是否为已开计费的正确账号;或确认GOOGLE_APPLICATION_CREDENTIALS环境变量指向的服务账号密钥,所属项目已开计费且拥有存储桶写入权限。
    • GCP环境运行:检查实例/服务绑定的服务账号是否属于目标项目,是否拥有roles/storage.objectCreator及以上权限,同时确认项目计费状态正常。
  • 确认存储桶与项目的关联
    检查存储桶pdf-split-ingestion是否确实属于项目spring-b-357511,避免因项目ID错误,请求到了未开计费的其他项目下的存储桶,可通过GCP控制台存储桶详情页查看所属项目。

  • 检查凭据权限范围
    确保使用的账号拥有足够权限:至少需要storage.objects.create权限,可通过绑定Storage Object Creator角色实现;同时确认没有针对该账号设置计费配额限制或IAM拒绝规则。

  • 升级GCP Storage客户端库
    旧版本客户端库可能存在计费校验逻辑问题,尝试升级google-cloud-storage依赖到最新稳定版,例如在pom.xml中更新:

    <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>google-cloud-storage</artifactId>
        <version>2.22.0</version> <!-- 替换为最新版本 -->
    </dependency>
    
  • 显式指定服务账号密钥
    为排除默认凭据的问题,可在代码中显式指定服务账号密钥路径,确保使用正确账号:

    Storage storage = StorageOptions.newBuilder()
        .setProjectId(projectId)
        .setCredentials(ServiceAccountCredentials.fromStream(new FileInputStream("/path/to/your/service-account-key.json")))
        .build()
        .getService();
    

内容的提问来源于stack exchange,提问作者Aravinth kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:18:22