我正在尝试创建一个签名策略,供用户在谷歌云存储上上传文件。
我在这里面临的问题是文件名,我希望用户在上传时提供文件名,如GCS官方文件中所述,如果你想从用户那里提供文件名为${filename},这不起作用,因为我收到以下错误:
<?xml version='1.0' encoding='UTF-8'?>
<Error>
<Code>InvalidPolicyDocument</Code>
<Message>The content of the form does not meet the conditions specified in the policy document.</Message>
<Details>Failed condition: {"key":"${filename}"}</Details>
</Error>
我已经尝试过用S3的createPresignedPost方法做同样的操作,它运行得很好。
参考:https://cloud.google.com/storage/docs/xml-api/post-object-forms
如有任何帮助,我们将不胜感激。
从GCS:生成策略的My Node.js代码
const { Storage } = require('@google-cloud/storage');
const storage = new Storage();
generateSignedPolicy = () => {
const bucket = 'some-bucket';
const file = storage.bucket(bucket).file("someFolder/${filename}");
const options = {
expires: Date.now() + (1000 * 300),
conditions : [
{ bucket : bucket },
]
};
return new Promise((resolve, reject) => {
file.generateSignedPostPolicyV4(options)
.then(([res]) => resolve(res))
.catch(error => reject(error))
})
}
使用上述代码生成的策略:
{
"url": "https://storage.googleapis.com/some-bucket/",
"fields": {
"key": "someFolder/${filename}",
"x-goog-date": "20221015T212358Z",
"x-goog-credential": "credential",
"x-goog-algorithm": "GOOG4-RSA-SHA256",
"policy": "policy",
"x-goog-signature": "signature"
}
}
错误详细信息显示:Failed condition: {"key":"${filename}"}
我看了上面写的代码,发现您正试图将一个模板变量放入一个普通字符串中。只能在模板字符串中使用${XXX}。
const file = storage.bucket(bucket).file("${filename}");
应为:
const file = storage.bucket(bucket).file(`${filename}`);
由于您没有修改任何关于文件名的内容,您可以将其简化为:
const file = storage.bucket(bucket).file(filename);
当考虑变量文件名时,此代码似乎有效:
const { Storage } = require('@google-cloud/storage');
const bucket = 'my-bucket';
const storage = new Storage();
async function generateSignedPolicy() {
const file = storage
.bucket(bucket)
.file("someFolder/${filename}");
const [response] = await file.generateSignedPostPolicyV4({
expires: Date.now() + (1000 * 300),
conditions: [],
fields: {
bucket,
acl: 'private',
}
});
// console.log(response);
// Create an HTML form with the provided policy
let output = `<form action="${response.url}" method="POST" enctype="multipart/form-data">n`;
// Include all fields returned in the HTML form as they're required
for (const name of Object.keys(response.fields)) {
const value = response.fields[name];
output += ` <input name="${name}" value="${value}" type="hidden"/>n`;
}
output += ' <input type="file" name="file"/><br />n';
output += ' <input type="submit" value="Upload File"/><br />n';
output += '</form>';
console.log(output);
// Copy file contents to an HTML file and open that file in your browser, select a file, and upload
// There will be a 204 response and the file will be uploaded in someFolder
}
generateSignedPolicy().catch((err) => {
console.error(err);
})
我删除了所有条件,并将bucket设置为字段。