video-flow-b/api/common.ts

172 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Common API 相关接口
import { baseUrl } from '@/lib/env';
export interface ApiResponse<T = any> {
code: number
successful: boolean
message: string
data: T
}
export interface TokenResponse {
code: number
message: string
data: {
token: string
}
successful: boolean
}
export interface TokenWithDomainResponse {
code: number
message: string
data: {
token: string
domain: string
}
successful: boolean
}
export interface QiniuUploadResponse {
hash: string
key: string
url?: string
}
/**
* 获取当前客户端的 UA 与设备信息
*/
export const getClientUserData = (): { user_agent: string; is_mobile: 1 | 0 } => {
try {
const ua = typeof navigator !== 'undefined' && navigator.userAgent ? navigator.userAgent : ''
const isMobile = /Mobile|Android|iPhone/i.test(ua)
return { user_agent: ua, is_mobile: isMobile ? 1 : 0 }
} catch {
return { user_agent: '', is_mobile: 0 }
}
}
// 获取七牛云上传token包含domain
export const getUploadToken = async (timeoutMs: number = 10000): Promise<{ token: string, domain: string }> => {
// 添加超时控制
const controller = new AbortController()
const timeoutId = setTimeout(() => {
console.log(`Request timeout${timeoutMs / 1000}saborting...`)
controller.abort()
}, timeoutMs)
try {
const response = await fetch(`${baseUrl}/common/get-upload-token`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${localStorage.getItem("token")}`
},
signal: controller.signal,
mode: "cors",
})
// 请求完成后清除超时
clearTimeout(timeoutId)
if (!response.ok) {
const errorText = await response.text()
console.error("Get token response error:", response.status, errorText)
throw new Error(`Get token failed: ${response.status} ${response.statusText}`)
}
const result: TokenWithDomainResponse | TokenResponse = await response.json()
console.log("Get token response:", result)
if (result.code === 0 && result.successful && result.data.token) {
console.log("Successfully get token")
// Support both old and new API response formats
const domain = 'domain' in result.data ? result.data.domain : 'cdn.qikongjian.com'
return {
token: result.data.token,
domain: domain
}
} else {
throw new Error(result.message || "Get token failed, server did not return a valid token")
}
} catch (error) {
clearTimeout(timeoutId)
console.error("Get upload token failed:", error)
if (error instanceof Error) {
if (error.name === "AbortError") {
throw new Error("Request timeout, please check your network connection")
} else if (error.message.includes("Failed to fetch")) {
throw new Error("Network connection failed, possibly due to CORS policy or server unreachable")
}
}
throw error
}
}
// 生成唯一文件名
export const generateUniqueFileName = (originalName: string): string => {
const timestamp = Date.now()
const randomStr = Math.random().toString(36).substring(2, 8)
const extension = originalName.split(".").pop()
return `videos/${timestamp}_${randomStr}.${extension}`
}
// 七牛云上传
export const uploadToQiniu = async (
file: File,
token: string,
onProgress?: (progress: number) => void
): Promise<string> => {
const uniqueFileName = generateUniqueFileName(file.name)
const formData = new FormData()
formData.append("token", token)
formData.append("key", uniqueFileName)
formData.append("file", file)
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.upload.addEventListener("progress", (event) => {
if (event.lengthComputable && onProgress) {
const progress = Math.round((event.loaded / event.total) * 100)
onProgress(progress)
}
})
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 300) {
try {
const response: QiniuUploadResponse = JSON.parse(xhr.responseText)
const qiniuUrl = `https://cdn.qikongjian.com/${response.key || uniqueFileName}`
console.log("Qiniu cloud upload success:", response)
resolve(qiniuUrl)
} catch (error) {
console.error("Parse response failed:", error, "Original response:", xhr.responseText)
reject(new Error(`Parse upload response failed: ${xhr.responseText}`))
}
} else {
console.error("Qiniu cloud upload failed:", xhr.status, xhr.statusText, xhr.responseText)
reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`))
}
})
xhr.addEventListener("error", (e) => {
console.error("Upload network error:", e)
reject(new Error("Network error, upload failed"))
})
xhr.addEventListener("abort", () => {
reject(new Error("Upload aborted"))
})
xhr.open("POST", "https://up-z2.qiniup.com")
xhr.send(formData)
})
}