diff --git a/app/components/auth/Register.tsx b/app/components/auth/Register.tsx index 06d30f4..1246174 100644 --- a/app/components/auth/Register.tsx +++ b/app/components/auth/Register.tsx @@ -1,10 +1,8 @@ import React, { useState } from 'react'; import { useNavigate } from '@remix-run/react'; import { useAuth } from '~/hooks/useAuth'; -import { getOSSUploadPolicy } from '~/utils/aliyunOSS'; - -// 导入我们刚刚定义的接口 import type { RegisterResponse } from '~/routes/api.auth.register'; +import { uploadToOSS } from '~/utils/uploadToOSS'; export function Register() { const [phone, setPhone] = useState(''); @@ -26,26 +24,8 @@ export function Register() { return; } try { - // 获取OSS上传策略 - const ossPolicy = await getOSSUploadPolicy(); - // 上传头像到OSS - const formData = new FormData(); - Object.entries(ossPolicy).forEach(([key, value]) => { - formData.append(key, value as string); - }); - formData.append('file', avatar); - - const uploadResponse = await fetch(ossPolicy.host, { - method: 'POST', - body: formData, - }); - - if (!uploadResponse.ok) { - throw new Error('头像上传失败'); - } - - const avatarUrl = `${ossPolicy.host}/${ossPolicy.key}`; + const avatarUrl = await uploadToOSS(avatar); // 注册用户 const registerResponse = await fetch('/api/auth/register', { @@ -65,6 +45,7 @@ export function Register() { if (registerResponse.ok && data.token && data.user) { // 注册成功后直接登录 login(data.token, data.user); + navigate('/dashboard'); } else { alert(data.error || '注册失败,请稍后再试'); } diff --git a/app/routes/api.oss.upload-policy.ts b/app/routes/api.oss.upload-policy.ts new file mode 100644 index 0000000..84e80a2 --- /dev/null +++ b/app/routes/api.oss.upload-policy.ts @@ -0,0 +1,13 @@ +import { json } from '@remix-run/node'; +import type { LoaderFunction } from '@remix-run/node'; +import { getOSSUploadPolicy, type OSSPolicy } from '~/utils/aliyunOSS.server'; + +export const loader: LoaderFunction = async () => { + try { + const policy: OSSPolicy = await getOSSUploadPolicy(); + return json(policy); + } catch (error) { + console.error('Error generating OSS upload policy:', error); + return json({ error: '获取上传策略失败' }, { status: 500 }); + } +}; diff --git a/app/utils/aliyunOSS.server.ts b/app/utils/aliyunOSS.server.ts new file mode 100644 index 0000000..87582d6 --- /dev/null +++ b/app/utils/aliyunOSS.server.ts @@ -0,0 +1,47 @@ +import OSS from 'ali-oss'; +import { v4 as uuidv4 } from 'uuid'; +import { env } from 'node:process'; + +// 更新 OSSPolicy 接口以匹配实际返回的数据 +export interface OSSPolicy { + OSSAccessKeyId: string; + policy: string; + Signature: string; + host: string; + expire: number; + key: string; +} + +const ossConfig = { + region: env.ALIYUN_OSS_REGION!, + accessKeyId: env.ALIYUN_OSS_ACCESS_KEY_ID!, + accessKeySecret: env.ALIYUN_OSS_ACCESS_KEY_SECRET!, + bucket: env.ALIYUN_OSS_BUCKET!, +}; + +if (Object.values(ossConfig).some(value => value === undefined)) { + throw new Error('缺少必要的阿里云 OSS 配置'); +} + +export async function getOSSUploadPolicy(): Promise { + const client = new OSS(ossConfig); + const date = new Date(); + date.setDate(date.getDate() + 1); + const policy = { + expiration: date.toISOString(), + conditions: [ + ['content-length-range', 0, 1048576000], // 限制文件大小最大为1GB + ['starts-with', '$key', 'avatars/'] + ] + }; + + const formData = await client.calculatePostSignature(policy); + const key = `avatars/${uuidv4()}`; + + return { + ...formData, + key, + host: `https://${ossConfig.bucket}.${ossConfig.region}.aliyuncs.com`, + expire: Math.floor(date.getTime() / 1000) + }; +} diff --git a/app/utils/uploadToOSS.ts b/app/utils/uploadToOSS.ts new file mode 100644 index 0000000..a451763 --- /dev/null +++ b/app/utils/uploadToOSS.ts @@ -0,0 +1,34 @@ +import type { OSSPolicy } from './aliyunOSS.server'; + +export async function uploadToOSS(file: File): Promise { + try { + // 获取OSS上传策略 + const policyResponse = await fetch('/api/oss/upload-policy'); + if (!policyResponse.ok) { + throw new Error('获取上传策略失败'); + } + const ossPolicy: OSSPolicy = await policyResponse.json(); + + // 上传文件到OSS + const formData = new FormData(); + Object.entries(ossPolicy).forEach(([key, value]) => { + formData.append(key, value.toString()); + }); + formData.append('file', file); + + const uploadResponse = await fetch(ossPolicy.host, { + method: 'POST', + body: formData, + }); + + if (!uploadResponse.ok) { + throw new Error('文件上传失败'); + } + + // 返回文件的URL + return `${ossPolicy.host}/${ossPolicy.key}`; + } catch (error) { + console.error('Upload to OSS failed:', error); + throw error; + } +}