前端實作
<input type="file" id="upfile" accept="image/*">
<input type="hidden" name="avatar" id="avatar-url">
<img id="preview" style="max-width:200px;display:none;">
$('#upfile').on('change', function() {
const file = this.files[0];
if (!file) return;
const formData = new FormData();
formData.append('policy', window.UPYUN_POLICY); // 後端簽名策略
formData.append('signature', window.UPYUN_SIGNATURE); // 後端簽名
formData.append('file', file);
$.ajax({
url: 'https://v0.api.upyun.com/your-bucket',
type: 'POST',
data: formData,
processData: false,
contentType: false,
xhr: () => {
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = e => {
if (e.lengthComputable) {
console.log(`上傳進度: ${(e.loaded/e.total*100).toFixed(1)}%`);
}
};
return xhr;
},
success: res => {
$('#avatar-url').val(res.url);
$('#preview').attr('src', res.url).show();
},
error: (xhr) => console.error('上傳失敗', xhr.responseText)
});
});
後端簽名生成
use Upyun\Upyun;
$upyun = new Upyun('bucket-name', 'operator', 'password');
$policy = [
'bucket' => 'bucket-name',
'expiration' => time() + 3600,
'save-key' => '/uploads/{year}{mon}{day}/{random32}{.suffix}',
'allow-file-type' => 'jpg,jpeg,png,gif,webp',
];
$encodedPolicy = base64_encode(json_encode($policy));
$signature = $upyun->sign($encodedPolicy);
// 輸出給前端 JS 變數
echo "";
優勢與注意
- 直傳又拍雲,不經過應用伺服器,節省頻寬與 I/O
- Policy 含過期時間、儲存路徑規則、檔案型別限制,安全可控
- IE10+ 支援 FormData,舊瀏覽器可回退至 iframe/form 方案
- 大檔案建議啟用分片上傳(又拍雲支援可斷點續傳)