【问题标题】:Blob is created but File is not uploaded using SignedURL已创建 Blob,但未使用 SignedURL 上传文件
【发布时间】:2018-10-25 05:12:12
【问题描述】:

我正在使用 SignedURL 将文件直接上传到 Cloud Storage,而无需通过 App Engine 实例。我正在遵循的过程是:

  1. 创建一个空对象并为该对象生成一个 SignedURL

    Storage storage = null;
    
    try{
    
    FileInputStream credentialsStream = new FileInputStream("JSONFile");
    
    Credentials credentials = GoogleCredentials.fromStream(credentialsStream);
    
    storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();
    
    }catch(IOException e) {
    
      e.printStackTrace();
    
    }
    
    Acl aclObject = Acl.of(User.ofAllUsers(),Role.OWNER);
    
    List<Acl> aclAccess = new ArrayList<>();
    
    aclAccess.add(aclObject);
    
    //BucketName and User name are Strings.
    BlobId blobId = BlobId.of(BUCKET_NAME,USER_NAME+"TeamLogo");
    
    BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setAcl(aclAccess).setContentType("image/jpeg").build();
    
    Blob blob = storage.create(blobInfo); 
    

至此,云存储中创建了一个空对象

我正在为此空对象生成一个签名URL,这样当用户上传文件时,文件的内容将替换空对象

    HttpMethod httpMethod = HttpMethod.PUT;

    ServiceAccountSigner signer = ServiceAccountCredentials.newBuilder().setClientId(CLIENT_ID).setClientEmail(CLIENT_EMAIL).setPrivateKey(PRIVATEKEY).setPrivateKeyId(PRIVATE_KEY_ID).build()

    URL url = blob.signUrl(10,TimeUnit.MINUTES,Storage.SignUrlOption.httpMethod(httpMethod),Storage.SignUrlOption.signWith(signer),Storage.SignUrlOption.withContentType());
    return url;

用于处理文件上传的 HTML 代码

<form action="${signedURL}" method="put" enctype="multipart/form-data">
 <label>Enter Your User Name</label><br>
<input type="text" name="UserName" ><br><br>
<label>Enter Your Team Name</label><br>
<input type="text" name="TeamName" ><br><br>
<label>Upload Team Logo</label><br>
<input type="file" name="myFile" required="required"><br><br>
<input type="submit" value="Create Team">
<input type="hidden" name="success_action_redirect" value="http://localhost:8080/register">
</form>

选择文件并点击上传后,我选择的文件没有上传到云存储,它正在加载此页面(带有 URL 的白色页面)。

我没有达到我想要的结果。我的代码中缺少什么?云存储的 Java 文档并没有为像我这样的新手提供完整的图片。有人请在这方面帮助我。

更新:对云存储的 Javascript AJAX 请求

var signedURL;
function uploadFile(){
    var urlxhr = new XMLHttpRequest();
    //To get the SignedURL from server side
    urlxhr.open('GET','http://localhost:8080/getsignedurl')
    urlxhr.send();
    urlxhr.onreadystatechange = function(){
        if (urlxhr.readyState == 4 && urlxhr.status == 200) {	
            signedURL = urlxhr.responseText;
            var file = document.getElementById("myFile").files[0]
            var formData = new FormData();
            formData.append('imageFile',file);
            var storageXhr = new XMLHttpRequest();
            storageXhr.open('PUT',signedURL,true);
            storageXhr.onload = () => {
                if(storageXhr.status == 200){
                    alert("File Successfully Uploaded");
                }else{
                    alert("Something went Wrong");
                }
            };
            storageXhr.onerror = () => {
                alert("An Error occured while Uploading file");
            };
            storageXhr.setRequestHeader('Content-Type',file.type);
            storageXhr.send(formData);
        }
    }

    


}
<!-- Uploading Directly to Cloud storage by AJAX Request -->
<form action="#" method="put" onsubmit="uploadFile()">
<label>Select Your Team Logo</label>
<input type="file" id="myFile" required="required">
<input type="submit" value="Upload File">
</form>
</div>

【问题讨论】:

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


    【解决方案1】:

    您似乎正在尝试使用POST Object 命令,但使用的是PUT Object 命令。例如,您正在使用success_action_redirect,这仅适用于 POST 对象命令。 PUT Object 命令不接受这种方式的表单数据。

    您可以使用带有签名 URL 的 PUT 对象命令,但不能以这种方式。相反,您将使用 JavaScript 来制作文件内容的上传。

    如果您打算使用 HTML 表单,则需要使用 POST 对象命令。不过,签署这些请求的规则有些不同。查看文档的“政策文件”部分:https://cloud.google.com/storage/docs/xml-api/post-object#usage_and_examples

    因此,要更改上面的示例,请将方法切换到 POST,添加一个 policy 字段和一个由服务器制作的 Signature 字段,就像您现在签署您的请求一样,然后切换对“https://storage.googleapis.com/bucket_name”的操作。

    【讨论】:

    • 嗨,布兰登,感谢您的回复。就像你建议的那样,我编写了一个 Javascript 函数来将文件上传到云存储,但是当我向我在服务器端生成的签名 URL 发出 PUT 请求时,我从 GCS 收到 404 错误。这给我留下了一个问题。我们真的需要一个签名的URL,或者我可以直接使用https://storage.googleapis.com/[BUCKET_NAME]/[OBJECT_NAME],正如这篇文章中提到的Request Endpoints XML API
    • 我已经编辑了问题并在我的代码中添加了 Javascript 函数
    猜你喜欢
    • 2019-10-26
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    相关资源
    最近更新 更多