sparkyspider
sparkyspider

Reputation: 13529

Java Google Cloud Storage API: How to set new uploaded objects public

I'm writing code to upload publicly accessible files to Google Cloud Storage, however, they are uploaded, but don't have the "Shared Publicly" checkbox checked.

I use the following code to set up my Google connection:

    log.info("Setting up Google Cloud Storage");

    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = new JacksonFactory();

    List<String> scopes = new ArrayList<>();
    scopes.add(StorageScopes.CLOUD_PLATFORM);

    Credential credential = new GoogleCredential.Builder()
            .setTransport(httpTransport)
            .setJsonFactory(jsonFactory)
            .setServiceAccountId("157264856793-sl14obknv58bi73m2co92oabrara9l8c@developer.gserviceaccount.com")
            .setServiceAccountPrivateKeyFromP12File(resourceLoader.getResource("classpath:google-auth.p12").getFile())
            .setServiceAccountScopes(scopes).build();

    storage = new Storage.Builder(httpTransport, jsonFactory, credential).setApplicationName("nitro-login").build();

    log.info("Google Cloud Storage set up");

And then the following code to write the files:

public void save(String filename, MultipartFile mpf) {

    try {

        log.info("Uploading " + filename + "...");

        InputStreamContent content = new InputStreamContent(mpf.getContentType(), mpf.getInputStream());
        content.setLength(mpf.getSize());
        StorageObject metaData = new StorageObject();
        Storage.Objects.Insert insert = storage.objects().insert("nitro-resources", metaData, content).setName(filename);
        insert.getMediaHttpUploader().setDisableGZipContent(true);
        insert.execute();

        log.info("Uploaded");

    } catch (IOException io) {
        log.error("Crash");

        io.printStackTrace();
    }
}

I've tried the following:

GSUtil

./gsutil acl ch -u AllUsers:R gs://nitro-resources
./gsutil defacl ch -u AllUsers:R gs://nitro-resources

And also calling setACL on my mataData object:

metaData.setAcl(ImmutableList.of(new ObjectAccessControl().setEntity("allUsers").setRole("READER")));

And also calling setPredefinedAcl in the insert object.

insert.setPredefinedAcl("publicRead");

Interestingly the best result is when I leave both ACL-related statements out. Then at least I get the option to manually tick the checkbox in the Google Cloud Console. I'd like it ticked by default.

Upvotes: 1

Views: 1008

Answers (2)

sparkyspider
sparkyspider

Reputation: 13529

I'm not sure what actually changed it, and why its working now. Here are the things I did since:

  1. Disabled the HMAC / Interoperability key in the console.
  2. Rewrote the code

    try {
    
        InputStream p12InputSream;
        HttpTransport httpTransport;
        File tempFile;
    
        p12InputSream = resourceLoader.getResource("classpath:google-auth.p12").getInputStream();
        tempFile = File.createTempFile("temp", "temp");
        IOUtils.copy(p12InputSream, new FileOutputStream(tempFile));
    
        httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        JsonFactory jsonFactory = new JacksonFactory();
    
        List<String> scopes = new ArrayList<>();
        scopes.add(StorageScopes.CLOUD_PLATFORM);
        scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
    
        Credential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(jsonFactory)
                .setServiceAccountId("157264856793-sl14obknv58bi73m2co92oabrara9l8c@developer.gserviceaccount.com")
                .setServiceAccountPrivateKeyFromP12File(tempFile)
                .setServiceAccountScopes(scopes)
                .build();
    
        storage = new Storage.Builder(httpTransport, jsonFactory, credential).setApplicationName("nitro-login").build();
    
        InputStreamContent content = new InputStreamContent(mpf.getContentType(), mpf.getInputStream());
        StorageObject metaData = new StorageObject().setName(filename);
        Storage.Objects.Insert insert = storage.objects().insert("nitro-resources", metaData, content);
        insert.execute();
    
    catch (Exception ex) {} 
    

Somehow that did it.

Upvotes: 0

Mike Schwartz
Mike Schwartz

Reputation: 12155

The gsutil acl ch command you used is setting the bucket's ACL. If you want to set the ACLs on objects that already have been uploaded try:

gsutil -m acl -R ch -u AllUsers:R gs://nitro-resources

The gsutil defacl command you used should work fine, but note that the default object ACL is applied when objects are uploaded - so any objects that were already present in the bucket when you used this command would have the default ACL that was previously set on the bucket (by default that's project-private), or the ACL you changed to using gsutil acl ch.

Upvotes: 3

Related Questions