优化图文页
This commit is contained in:
+52
-52
@@ -14,7 +14,7 @@ import {
|
||||
downloadFile,
|
||||
fileExists,
|
||||
getFileInfo,
|
||||
} from './minio';
|
||||
} from "./minio";
|
||||
|
||||
// ========================================
|
||||
// 1. 上传文件示例
|
||||
@@ -25,15 +25,15 @@ import {
|
||||
*/
|
||||
async function uploadAvatar(file: File, userId: string) {
|
||||
// 验证文件类型
|
||||
const allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
const allowedTypes = ["jpg", "jpeg", "png", "gif", "webp"];
|
||||
if (!validateFileType(file.name, allowedTypes)) {
|
||||
throw new Error('不支持的图片格式');
|
||||
throw new Error("不支持的图片格式");
|
||||
}
|
||||
|
||||
// 验证文件大小(5MB)
|
||||
const maxSize = 5 * 1024 * 1024;
|
||||
if (!validateFileSize(file.size, maxSize)) {
|
||||
throw new Error('文件大小超过限制(最大5MB)');
|
||||
throw new Error("文件大小超过限制(最大5MB)");
|
||||
}
|
||||
|
||||
// 生成唯一文件名,存储在 avatars 目录下
|
||||
@@ -41,8 +41,8 @@ async function uploadAvatar(file: File, userId: string) {
|
||||
|
||||
// 上传文件
|
||||
const url = await uploadFile(file, path, {
|
||||
'Content-Type': file.type,
|
||||
'User-Id': userId,
|
||||
"Content-Type": file.type,
|
||||
"User-Id": userId,
|
||||
});
|
||||
|
||||
return { url, path };
|
||||
@@ -52,28 +52,28 @@ async function uploadAvatar(file: File, userId: string) {
|
||||
* 上传文章封面图
|
||||
*/
|
||||
async function uploadPostCover(file: File, postId: string) {
|
||||
const allowedTypes = ['jpg', 'jpeg', 'png', 'webp'];
|
||||
const allowedTypes = ["jpg", "jpeg", "png", "webp"];
|
||||
if (!validateFileType(file.name, allowedTypes)) {
|
||||
throw new Error('不支持的图片格式');
|
||||
throw new Error("不支持的图片格式");
|
||||
}
|
||||
|
||||
const maxSize = 10 * 1024 * 1024; // 10MB
|
||||
if (!validateFileSize(file.size, maxSize)) {
|
||||
throw new Error('文件大小超过限制(最大10MB)');
|
||||
throw new Error("文件大小超过限制(最大10MB)");
|
||||
}
|
||||
|
||||
// 按日期组织文件
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
|
||||
const path = generateUniqueFileName(
|
||||
file.name,
|
||||
`posts/${year}/${month}/covers`
|
||||
`posts/${year}/${month}/covers`,
|
||||
);
|
||||
|
||||
const url = await uploadFile(file, path);
|
||||
|
||||
|
||||
return { url, path };
|
||||
}
|
||||
|
||||
@@ -81,27 +81,27 @@ async function uploadPostCover(file: File, postId: string) {
|
||||
* 上传文章内容中的图片
|
||||
*/
|
||||
async function uploadPostImage(file: File, postId: string) {
|
||||
const allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
const allowedTypes = ["jpg", "jpeg", "png", "gif", "webp"];
|
||||
if (!validateFileType(file.name, allowedTypes)) {
|
||||
throw new Error('不支持的图片格式');
|
||||
throw new Error("不支持的图片格式");
|
||||
}
|
||||
|
||||
const maxSize = 5 * 1024 * 1024; // 5MB
|
||||
if (!validateFileSize(file.size, maxSize)) {
|
||||
throw new Error('文件大小超过限制(最大5MB)');
|
||||
throw new Error("文件大小超过限制(最大5MB)");
|
||||
}
|
||||
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
|
||||
const path = generateUniqueFileName(
|
||||
file.name,
|
||||
`posts/${year}/${month}/images`
|
||||
`posts/${year}/${month}/images`,
|
||||
);
|
||||
|
||||
const url = await uploadFile(file, path);
|
||||
|
||||
|
||||
return { url, path };
|
||||
}
|
||||
|
||||
@@ -126,9 +126,9 @@ function getPublicFileUrl(path: string) {
|
||||
async function deleteAvatar(avatarPath: string) {
|
||||
try {
|
||||
await deleteFile(avatarPath);
|
||||
console.log('头像删除成功');
|
||||
console.log("头像删除成功");
|
||||
} catch (error) {
|
||||
console.error('删除头像失败:', error);
|
||||
console.error("删除头像失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -140,22 +140,22 @@ async function deletePostImages(postId: string) {
|
||||
try {
|
||||
// 列出文章相关的所有图片
|
||||
const files = await listFiles(`posts/`, true);
|
||||
|
||||
|
||||
// 过滤出该文章的图片(根据实际情况调整逻辑)
|
||||
const postFiles = files.filter(file =>
|
||||
file.name?.includes(postId)
|
||||
);
|
||||
const postFiles = files.filter((file) => file.name?.includes(postId));
|
||||
|
||||
// 批量删除
|
||||
const paths = postFiles.map(f => f.name).filter((name): name is string => !!name);
|
||||
|
||||
const paths = postFiles
|
||||
.map((f) => f.name)
|
||||
.filter((name): name is string => !!name);
|
||||
|
||||
if (paths.length > 0) {
|
||||
const { deleteFiles } = await import('./minio');
|
||||
const { deleteFiles } = await import("./minio");
|
||||
await deleteFiles(paths);
|
||||
console.log(`删除了 ${paths.length} 个文件`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除文章图片失败:', error);
|
||||
console.error("删除文章图片失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -170,15 +170,15 @@ async function deletePostImages(postId: string) {
|
||||
async function getUserAvatars(userId: string) {
|
||||
try {
|
||||
const files = await listFiles(`avatars/${userId}/`, false);
|
||||
|
||||
return files.map(file => ({
|
||||
|
||||
return files.map((file) => ({
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
lastModified: file.lastModified,
|
||||
url: file.name ? getFileUrl(file.name) : null,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('获取用户头像列表失败:', error);
|
||||
console.error("获取用户头像列表失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -188,16 +188,16 @@ async function getUserAvatars(userId: string) {
|
||||
*/
|
||||
async function getPostCoversByMonth(year: number, month: number) {
|
||||
try {
|
||||
const monthStr = String(month).padStart(2, '0');
|
||||
const monthStr = String(month).padStart(2, "0");
|
||||
const files = await listFiles(`posts/${year}/${monthStr}/covers/`, false);
|
||||
|
||||
return files.map(file => ({
|
||||
|
||||
return files.map((file) => ({
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
url: file.name ? getFileUrl(file.name) : null,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('获取封面列表失败:', error);
|
||||
console.error("获取封面列表失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -223,15 +223,15 @@ async function checkAvatarExists(avatarPath: string): Promise<boolean> {
|
||||
async function getFileDetails(path: string) {
|
||||
try {
|
||||
const info = await getFileInfo(path);
|
||||
|
||||
|
||||
return {
|
||||
size: info.size,
|
||||
lastModified: info.lastModified,
|
||||
etag: info.etag,
|
||||
contentType: info.metaData?.['content-type'],
|
||||
contentType: info.metaData?.["content-type"],
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取文件信息失败:', error);
|
||||
console.error("获取文件信息失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -247,7 +247,7 @@ async function downloadFileToBuffer(path: string): Promise<Buffer> {
|
||||
try {
|
||||
return await downloadFile(path);
|
||||
} catch (error) {
|
||||
console.error('下载文件失败:', error);
|
||||
console.error("下载文件失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -258,42 +258,42 @@ async function downloadFileToBuffer(path: string): Promise<Buffer> {
|
||||
|
||||
/**
|
||||
* Next.js API Route 示例:上传文件
|
||||
*
|
||||
*
|
||||
* 使用方法:
|
||||
*
|
||||
*
|
||||
* // app/api/upload/route.ts
|
||||
* import { uploadFile, generateUniqueFileName } from '@/lib/minio';
|
||||
*
|
||||
*
|
||||
* export async function POST(request: Request) {
|
||||
* const formData = await request.formData();
|
||||
* const file = formData.get('file') as File;
|
||||
*
|
||||
*
|
||||
* if (!file) {
|
||||
* return Response.json({ error: '没有文件' }, { status: 400 });
|
||||
* }
|
||||
*
|
||||
*
|
||||
* const path = generateUniqueFileName(file.name, 'uploads');
|
||||
* const url = await uploadFile(file, path);
|
||||
*
|
||||
*
|
||||
* return Response.json({ url, path });
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* Next.js API Route 示例:删除文件
|
||||
*
|
||||
*
|
||||
* // app/api/delete/route.ts
|
||||
* import { deleteFile } from '@/lib/minio';
|
||||
*
|
||||
*
|
||||
* export async function DELETE(request: Request) {
|
||||
* const { path } = await request.json();
|
||||
*
|
||||
*
|
||||
* if (!path) {
|
||||
* return Response.json({ error: '缺少文件路径' }, { status: 400 });
|
||||
* }
|
||||
*
|
||||
*
|
||||
* await deleteFile(path);
|
||||
*
|
||||
*
|
||||
* return Response.json({ success: true });
|
||||
* }
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user