生成Google云端存储对象的公共链接

时间:2015-12-22 02:04:40

标签: java google-app-engine google-cloud-storage blobstore

如何为用户通过BlobStore API提交的Google云端存储对象生成公共链接?

2 个答案:

答案 0 :(得分:4)

有几种方法可以提供公共GCS对象。一个是签名的URL。另一个是getServingUrl() App Engine方法。

但是,如果每个人都可以看到该对象,那么您可以做一些更简单的事情。设置对象的权限以向“AllUsers”授予READ权限,允许在没有任何身份验证的情况下读取对象,然后只需将用户引用到此路径:

https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME

就是这样!

您可以通过API或使用此gsutil命令将对象设置为可公开读取:gsutil acl ch -g AllUsers:R gs://BUCKET_NAME/OBJECT_NAME

答案 1 :(得分:0)

如何为Google云端存储对象生成公开链接?

  1. 通过console手动创建服务帐户,并生成.p12密钥文件。
  2. 用户将文件上传到使用以下内容生成的网址后
  3. blobstoreService.createUploadUrl("/fileUploadingHandler", 
            UploadOptions.Builder.withMaxUploadSizeBytes(1024*1024*10) // 10 MB max
                                 .googleStorageBucketName(BUCKET_NAME));
    

    servlet(处理/fileUploadingHandler)可以检索GCS对象的文件名并生成临时签名的公共链接,如下所示:

    Map<String, List<FileInfo>> fileInfoMap = blobstoreService.getFileInfos(request);
    List<FileInfo> fileInfos = fileInfoMap.get("fileName");
    FileInfo fileInfo = fileInfos.get(0);
    String[] parts = fileInfo.getGsObjectName().split("/"); // get rid of /gs/buck_name/
    String fileName = parts[parts.length - 1];
    String signedUrl = GcsUrlSigner.generateSignedUrl(fileName);
    // send the temporary public link (signedUrl) back to the user
    
    import com.google.api.client.util.Base64;
    
    import java.io.InputStream;
    import java.net.URLEncoder;
    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.Signature;
    
    /**
     * Created by Fouad on 22-Dec-15.
     */
    public class GcsUrlSigner
    {
        private static final String DEFAULT_BUCKET_NAME = "XXXXXXXX.appspot.com";
        private static final String PUBLIC_URL_SERVICE_ACCOUNT_EMAIL = "XXXXXXXX@XXXXXX.iam.gserviceaccount.com";
        private static final String PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PATH = "XXXXXX.p12"; // located in the same folder as GcsUrlSigner.java
        private static final String PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PASSWORD = "notasecret";
        private static final long PUBLIC_URL_EXPIRATION_SECONDS = System.currentTimeMillis() / 1000 + 60; // 60 seconds
    
        public static String generateSignedUrl(String objectName) throws Exception
        {
            return generateSignedUrl(DEFAULT_BUCKET_NAME, objectName);
        }
    
        public static String generateSignedUrl(String bucketName, String objectName) throws Exception
        {
            PrivateKey key = loadKeyFromPkcs12(PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PATH, PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PASSWORD.toCharArray());
            return getSigningURL(key, "GET", PUBLIC_URL_EXPIRATION_SECONDS, bucketName, objectName);
        }
    
        private static String getSigningURL(PrivateKey key, String verb, long expirationSeconds, String bucketName, String objectName) throws Exception
        {
            String url_signature = signString(key, verb + "\n\n\n" + expirationSeconds + "\n" + "/" + bucketName + "/" + objectName);
            String signed_url = "https://storage.googleapis.com/" + bucketName + "/" + objectName +
                    "?GoogleAccessId=" + PUBLIC_URL_SERVICE_ACCOUNT_EMAIL +
                    "&Expires=" + expirationMillis +
                    "&Signature=" + URLEncoder.encode(url_signature, "UTF-8");
            return signed_url;
        }
    
        private static PrivateKey loadKeyFromPkcs12(String filename, char[] password) throws Exception
        {
            InputStream is = GcsUrlSigner.class.getResourceAsStream(PUBLIC_URL_SERVICE_ACCOUNT_PKCS12_FILE_PATH);
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(is, password);
            return (PrivateKey) ks.getKey("privatekey", password);
        }
    
        private static String signString(PrivateKey key, String stringToSign) throws Exception
        {
            if(key == null) throw new Exception("Private Key not initalized");
    
            Signature signer = Signature.getInstance("SHA256withRSA");
            signer.initSign(key);
            signer.update(stringToSign.getBytes("UTF-8"));
    
            byte[] rawSignature = signer.sign();
    
            return new String(Base64.encodeBase64(rawSignature), "UTF-8");
        }
    }