Web端接收到服务端返回的上传Policy和签名后,使用HTML表单构建请求并设置上传回调。此请求使用POST表单上传来直接调用OBS的服务端,实现文件上传。
Web端接收到服务端的响应示例如下:
{
"accessKeyId": "****************", // 密钥AK
"bucket": "post-callback-demo", // 需要上传的桶名
"callbackBodyType": "application/json", // 响应体格式
"signature": "24*******************u8=", // POST上传的签名
"prefix": "demo", // POST上传对象名前缀
"host": "obs.cn-north-4.myhuaweicloud.com", // POST上传host地址
"callbackUrl": "http://obs-demo.huaweicloud.com:23450/callback", // POST上传回调的地址
"policy": "eyJleHBpcmF***************************************ifV19", // POST上传policy
"callbackBody": "key=$(key)&hash=$(etag)&fname=$(fname)&fsize=$(size)" // POST上传回调的请求体
}
使用HTML表单构建请求并设置上传回调的示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>华为云OBS表单上传</title>
</head>
<body>
<h1>OBS表单上传回调示例</h1>
<form>
<div class="form-group">
<label for="file" class="form-label">选择文件:</label>
<input type="file" class="form-control" id="file" name="file" required/>
</div>
<button name="submit" value="Upload" type="submit">上传到OBS</button>
</form>
<div id="result"></div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const form = document.querySelector("form");
const fileInput = document.querySelector("#file");
const resultDiv = document.getElementById("result");
form.addEventListener("submit", async (event) => {
event.preventDefault();
if (!fileInput.files.length) {
resultDiv.innerHTML = '<p style="color:red">请选择文件</p>';
return;
}
const file = fileInput.files[0];
if (!file) {
alert('请选择一个文件再上传。');
return;
}
const filename = file.name;
try {
// 1. 获取签名参数
resultDiv.innerHTML = '获取签名中...';
const response = await fetch(`/obs-post-callback-signature`);
const params = await response.json();
// 2. 构建表单数据
const formData = new FormData();
formData.append('key', params.prefix + "/" + filename);
formData.append('x-obs-acl', 'public-read');
formData.append('policy', params.policy);
formData.append('AccessKeyId', params.accessKeyId);
formData.append('signature', params.signature);
formData.append('callbackUrl', params.callbackUrl);
formData.append('callbackBody', params.callbackBody);
formData.append('callbackBodyType', params.callbackBodyType);
// 【可选】如果服务端签名使用了SecurityToken,在Form表单中也需要设置
// formData.append('x-obs-security-token', params['x-obs-security-token']);
formData.append('file', file);
// 3. 提交到OBS
resultDiv.innerHTML = '上传中...';
const obsEndpoint = `https://${params.bucket}.${params.host}`;
const uploadResponse = await fetch(obsEndpoint, {
method: 'POST',
body: formData
});
if (uploadResponse.status === 200) {
resultDiv.innerHTML = `<p style="color:green">上传成功! OBS路径: ${params.key}</p>
<p>回调通知将发送到: ${new URLSearchParams(atob(params.callback)).get('callbackUrl')}</p>`;
} else {
const error = await uploadResponse.text(); // 使用await
resultDiv.innerHTML = `<p style="color:red">上传失败! 状态码: ${uploadResponse.status}</p>
<p>${error}</p>`;
}
} catch (error) {
resultDiv.innerHTML = `<p style="color:red">发生错误: ${error.message}</p>`;
}
});
});
</script>
</body>
</html>
|