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>
 |