feat: add thumbnail upload support to course creation endpoint with multipart form data handling.

This commit is contained in:
JakkrapartXD 2026-01-28 14:38:11 +07:00
parent 19844f343b
commit cf12ef965e
3 changed files with 54 additions and 44 deletions

View file

@ -221,32 +221,32 @@ export class UserService {
// Upload to MinIO
await uploadFile(filePath, file.buffer, file.mimetype || 'image/jpeg');
// Update user profile with avatar URL
const avatarUrl = `${config.s3.endpoint}/${config.s3.bucket}/${filePath}`;
// Update or create profile
// Update or create profile - store only file path
if (user.profile) {
await prisma.userProfile.update({
where: { user_id: decoded.id },
data: { avatar_url: avatarUrl }
data: { avatar_url: filePath }
});
} else {
await prisma.userProfile.create({
data: {
user_id: decoded.id,
avatar_url: avatarUrl,
avatar_url: filePath,
first_name: '',
last_name: ''
}
});
}
// Generate presigned URL for response
const presignedUrl = await this.getAvatarPresignedUrl(filePath);
return {
code: 200,
message: 'Avatar uploaded successfully',
data: {
id: decoded.id,
avatar_url: avatarUrl
avatar_url: presignedUrl
}
};
} catch (error) {
@ -266,16 +266,13 @@ export class UserService {
/**
* Get presigned URL for avatar
*/
private async getAvatarPresignedUrl(avatarUrl: string): Promise<string | null> {
private async getAvatarPresignedUrl(avatarPath: string): Promise<string> {
try {
// Extract file path from stored URL or path
const filePath = avatarUrl.includes('/')
? `avatars/${avatarUrl.split('/').slice(-2).join('/')}`
: avatarUrl;
return await getPresignedUrl(filePath, 3600); // 1 hour expiry
// avatarPath is now stored as file path directly (e.g., avatars/1/filename.jpg)
return await getPresignedUrl(avatarPath, 3600); // 1 hour expiry
} catch (error) {
logger.warn(`Failed to generate presigned URL for avatar: ${error}`);
return null;
return '';
}
}