feat(auth): 优化注册头像上传及用户注册流程

This commit is contained in:
zyh 2024-10-22 04:21:09 +00:00
parent 21b1d9262e
commit 2ffa0b61d1
4 changed files with 97 additions and 22 deletions

View File

@ -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 || '注册失败,请稍后再试');
}

View File

@ -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 });
}
};

View File

@ -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<OSSPolicy> {
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)
};
}

34
app/utils/uploadToOSS.ts Normal file
View File

@ -0,0 +1,34 @@
import type { OSSPolicy } from './aliyunOSS.server';
export async function uploadToOSS(file: File): Promise<string> {
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;
}
}