fix:上传前从MinIO GET根路径同步服务器时间,解决RequestTimeTooSkewed

This commit is contained in:
97694732@qq.com 2026-06-05 11:12:37 +08:00
parent ab0a2f5aa8
commit 093c11c20e

View File

@ -68,6 +68,60 @@ function sha256Hex(str) {
return sha256(str) return sha256(str)
} }
// ====== 时间同步 ======
/** 缓存服务器时间偏移量(毫秒) */
var _timeOffset = 0
var _timeSyncing = false
/**
* MinIO 服务器同步时间
* 通过 GET 根路径获取 Date 响应头计算客户端与服务端的时间差
*/
function syncServerTime() {
return new Promise(function (resolve) {
if (_timeSyncing) {
// 已有同步请求在进行中,重试 500ms 后获取
setTimeout(function () { resolve(getServerDate()) }, 500)
return
}
_timeSyncing = true
var url = CFG.protocol + '://' + CFG.endpoint + '/'
var XHRClass = getXHR()
if (XHRClass) {
var xhr = new XHRClass()
xhr.open('GET', url, true)
xhr.onload = function () {
var serverDateStr = xhr.getResponseHeader('Date')
if (serverDateStr) {
var serverMs = new Date(serverDateStr).getTime()
if (serverMs) {
_timeOffset = serverMs - Date.now()
console.log('【MinIO】时间同步完成服务器偏移:', _timeOffset, 'ms')
}
}
_timeSyncing = false
resolve(getServerDate())
}
xhr.onerror = function () {
_timeSyncing = false
resolve(new Date())
}
xhr.send()
} else {
_timeSyncing = false
resolve(new Date())
}
})
}
/**
* 获取对齐服务器时间后的当前时间
*/
function getServerDate() {
return new Date(Date.now() + _timeOffset)
}
// ====== AWS V4 签名 ====== // ====== AWS V4 签名 ======
/** /**
@ -352,37 +406,39 @@ function getContentType(ext) {
*/ */
export function uploadImage(filePath, typeDir = 'Isbn') { export function uploadImage(filePath, typeDir = 'Isbn') {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
readFileAsBase64(filePath) syncServerTime().then(function (serverDate) {
.then(function (base64) { readFileAsBase64(filePath)
const arrayBuffer = base64ToArrayBuffer(base64) .then(function (base64) {
const arrayBuffer = base64ToArrayBuffer(base64)
// 构建对象路径:年-月-日/Isbn/uuid.ext // 构建对象路径(使用服务器时间)
const now = new Date() const now = serverDate
const datePath = now.getFullYear() + '-' + pad(now.getMonth() + 1) + '-' + pad(now.getDate()) const datePath = now.getFullYear() + '-' + pad(now.getMonth() + 1) + '-' + pad(now.getDate())
const ext = getFileExt(filePath) const ext = getFileExt(filePath)
const objectKey = datePath + '/' + typeDir + '/' + generateUUID() + '.' + ext const objectKey = datePath + '/' + typeDir + '/' + generateUUID() + '.' + ext
const contentType = getContentType(ext) const contentType = getContentType(ext)
// 构建 AWS V4 签名 // 构建 AWS V4 签名
const { authHeader, amzDate, host } = buildAuthHeader(objectKey, now) const { authHeader, amzDate, host } = buildAuthHeader(objectKey, now)
// PUT URL // PUT URL
const url = CFG.protocol + '://' + host + '/' + CFG.bucket + '/' + objectKey const url = CFG.protocol + '://' + host + '/' + CFG.bucket + '/' + objectKey
console.log('【MinIO上传】URL:', url) console.log('【MinIO上传】URL:', url)
console.log('【MinIO上传】contentType:', contentType) console.log('【MinIO上传】contentType:', contentType)
console.log('【MinIO上传】contentLength:', arrayBuffer.byteLength) console.log('【MinIO上传】contentLength:', arrayBuffer.byteLength)
// PUT 到 MinIO // PUT 到 MinIO
minioPut(url, arrayBuffer, contentType, authHeader, amzDate).then(function (resultUrl) { minioPut(url, arrayBuffer, contentType, authHeader, amzDate).then(function (resultUrl) {
resolve(resultUrl) resolve(resultUrl)
}).catch(function (err) { }).catch(function (err) {
reject(err)
})
})
.catch(function (err) {
reject(err) reject(err)
}) })
}) })
.catch(function (err) {
reject(err)
})
}) })
} }