yikart/AiToEarn · error · Error
获取上传签名失败
Error message
获取上传签名失败
What it means
thrown by getPresignedPostData when the backend response for requesting an OSS/S3 presigned upload is missing or its code !== 0 (the app's success code). It prefers the server-provided res.message and falls back to the generic '获取上传签名失败'. Indicates the upload could not even start because no signed POST data was issued.
Source
Thrown at project/aitoearn-web/src/api/materials/material.api.ts:79
return ownerId
? `${ownerId}/${hashedPrefix}${processedFileName}`
: `${hashedPrefix}${processedFileName}`
}
// 获取 R2 presigned post 数据
async function getPresignedPostData(fileName: string, fileSize: number, contentType: string, publicUploadId?: string) {
const res = await request<UploadSignData>({
url: getUploadRequestPath(publicUploadId),
method: 'POST',
data: {
filename: fileName,
size: fileSize,
type: getAssetType(fileName, contentType),
},
})
if (!res || res.code !== 0)
throw new Error(res?.message || '获取上传签名失败')
return res.data
}
async function confirmUpload(assetId: string, fallbackUrl: string, publicUploadId?: string) {
const confirmResponse = await request<ConfirmUploadData>({
url: getConfirmRequestPath(assetId, publicUploadId),
method: 'POST',
data: {
id: assetId,
},
})
if (!confirmResponse || confirmResponse.code !== 0)
throw new Error(confirmResponse?.message || '上传确认失败')
return confirmResponse.data?.url || fallbackUrl
}View on GitHub (pinned to d3aa8bea5b)
Solutions
- Log the full res object (code and message) — the server message usually names the exact cause.
- Re-authenticate if the backend code indicates 401/invalid token.
- Verify contentType/extension maps to a supported asset type in getAssetType.
- Check backend presign service config (bucket/keys) if the message points to server-side failure.
Example fix
// before
const res = await request<PresignedData>({ url: '/assets/presign', data })
if (!res || res.code !== 0) throw new Error(res?.message || '获取上传签名失败')
// after
if (!res) throw new Error('网络错误,无法获取上传签名')
if (res.code !== 0) throw new Error(`获取上传签名失败: ${res.message} (code=${res.code})`) Defensive patterns
Strategy: try-catch
Validate before calling
// before calling presign
if (!file.name || file.size <= 0) throw new Error('文件无效')
if (!isLoggedIn()) await refreshToken() Type guard
function hasPresignedData(r: unknown): r is { code: number; message?: string; data: PresignedPostData } {
const o = r as any
return !!o && typeof o.code === 'number' && !!o.data && typeof o.data.url === 'string'
} Try / catch
try {
const presigned = await getPresignedPostData(fileName, fileSize, contentType)
}
catch (e) {
showToast(e instanceof Error ? e.message : '获取上传签名失败')
return
} Prevention
- Check login state before initiating uploads; refresh tokens proactively.
- Support re-auth then retry when the presign code indicates auth failure.
- Validate file extensions/contentTypes against supported asset types up front.
- Log res.code and res.message server-side responses for every presign failure.
When it happens
Trigger: Calling getPresignedPostData with fileName/fileSize/contentType when the backend fails: auth failure (401 wrapped in res.code), asset type not recognized, backend storage service misconfigured, or request returned undefined (network/HTTP error swallowed by the request layer).
Common situations: Expired login token; backend S3/OSS credentials invalid; getAssetType returning an unsupported type for the file extension; request interceptor returning undefined on network error.
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/5bbf3b90c060e697.
Report an issue: GitHub.