diff --git a/apps/server/src/upload/share-code.service.ts b/apps/server/src/upload/share-code.service.ts index 9ac5d30..6dfebc6 100644 --- a/apps/server/src/upload/share-code.service.ts +++ b/apps/server/src/upload/share-code.service.ts @@ -38,16 +38,17 @@ export class ShareCodeService { }); if (existingShareCode) { - // 更新现有记录 + // 更新现有记录,但保留原有文件名 await db.shareCode.update({ where: { fileId }, data: { - fileName: fileName || null, code, expiresAt, isUsed: false, - // 如果提供了文件名且现有记录没有文件名,则更新文件名 - ...(fileName && !existingShareCode.fileName ? { fileName } : {}), + // 只在没有现有文件名且提供了新文件名时才更新文件名 + ...(fileName && !existingShareCode.fileName + ? { fileName } + : {}) }, }); } else { @@ -75,7 +76,7 @@ export class ShareCodeService { } } - async validateAndUseCode(code: string): Promise { + async validateAndUseCode(code: string): Promise { try { console.log(`尝试验证分享码: ${code}`); @@ -104,7 +105,8 @@ export class ShareCodeService { // 记录使用日志 this.logger.log(`Share code ${code} used for file ${shareCode.fileId}`); - return shareCode.fileId; + // 返回完整的分享码信息,包括文件名 + return shareCode; } catch (error) { this.logger.error('Failed to validate share code', error); return null; diff --git a/apps/server/src/upload/types.ts b/apps/server/src/upload/types.ts index 9ce1963..b841871 100755 --- a/apps/server/src/upload/types.ts +++ b/apps/server/src/upload/types.ts @@ -22,12 +22,13 @@ export interface UploadLock { } export interface ShareCode { + id: string; code: string; fileId: string; createdAt: Date; expiresAt: Date; isUsed: boolean; - fileName?: string; + fileName?: string | null; } export interface GenerateShareCodeResponse { diff --git a/apps/server/src/upload/upload.controller.ts b/apps/server/src/upload/upload.controller.ts index f15a1cf..b2dbd5e 100755 --- a/apps/server/src/upload/upload.controller.ts +++ b/apps/server/src/upload/upload.controller.ts @@ -47,11 +47,35 @@ export class UploadController { } @Get('share/:code') async validateShareCode(@Param('code') code: string) { - const fileId = await this.shareCodeService.validateAndUseCode(code); - if (!fileId) { - throw new NotFoundException('分享码无效或已过期'); + console.log('收到验证分享码请求,code:', code); + + const shareCode = await this.shareCodeService.validateAndUseCode(code); + console.log('验证分享码结果:', shareCode); + + if (!shareCode) { + throw new NotFoundException('分享码无效或已过期'); } - return { fileId }; + + // 获取文件信息 + const resource = await this.resourceService.findUnique({ + where: { fileId: shareCode.fileId }, + }); + console.log('获取到的资源信息:', resource); + + if (!resource) { + throw new NotFoundException('文件不存在'); + } + + // 直接返回正确的数据结构 + const response = { + fileId: shareCode.fileId, + fileName:shareCode.fileName || 'downloaded_file', + code: shareCode.code, + expiresAt: shareCode.expiresAt + }; + + console.log('返回给前端的数据:', response); // 添加日志 + return response; } @Get('share/info/:code') diff --git a/apps/web/src/app/main/admin/deptsettingpage/page.tsx b/apps/web/src/app/main/admin/deptsettingpage/page.tsx index 4727be5..7bfd279 100644 --- a/apps/web/src/app/main/admin/deptsettingpage/page.tsx +++ b/apps/web/src/app/main/admin/deptsettingpage/page.tsx @@ -9,12 +9,13 @@ const { TabPane } = Tabs; export default function DeptSettingPage() { const [uploadedFileId, setUploadedFileId] = useState(''); - const [fileNameMap, setFileNameMap] = useState>({}); + const [uploadedFileName, setUploadedFileName] = useState(''); // 使用您的 useTusUpload hook const { uploadProgress, isUploading, uploadError, handleFileUpload } = useTusUpload({ - onSuccess: (fileId: string) => { - setUploadedFileId(fileId); + onSuccess: (result) => { + setUploadedFileId(result.fileId); + setUploadedFileName(result.fileName); message.success('文件上传成功'); }, onError: (error: Error) => { @@ -30,27 +31,22 @@ export default function DeptSettingPage() { file, async (result) => { setUploadedFileId(result.fileId); - - // 在前端保存文件名映射(用于当前会话) - setFileNameMap(prev => ({ - ...prev, - [result.fileId]: file.name - })); - - // 上传成功后保存原始文件名到数据库 + setUploadedFileName(result.fileName); + try { - console.log('正在保存文件名到数据库:', file.name, '对应文件ID:', result.fileId); + console.log('正在保存文件名到数据库:', result.fileName, '对应文件ID:', result.fileId); - const response = await fetch('/api/upload/filename', { + const response = await fetch('http://localhost:3000/upload/filename', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ fileId: result.fileId, - fileName: file.name + fileName: file.name }), }); + const responseText = await response.text(); console.log('保存文件名响应:', response.status, responseText); @@ -82,53 +78,30 @@ export default function DeptSettingPage() { }; // 处理分享码验证成功 - const handleValidSuccess = async (fileId: string) => { + const handleValidSuccess = async (fileId: string, fileName: string) => { try { - // 构建下载URL - const response = await fetch(`/api/upload/download/${fileId}`); + // 构建下载URL(包含文件名参数) + const downloadUrl = `/upload/download/${fileId}?fileName=${encodeURIComponent(fileName)}`; + const response = await fetch(downloadUrl); if (!response.ok) { throw new Error('文件下载失败'); } - - // 获取文件名 - const contentDisposition = response.headers.get('content-disposition'); - console.log('Content-Disposition 头:', contentDisposition); - - let filename = fileNameMap[fileId] || 'downloaded-file'; // 优先使用本地缓存的文件名 - - if (contentDisposition) { - // 改进文件名提取逻辑 - const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; - const matches = filenameRegex.exec(contentDisposition); - if (matches && matches[1]) { - // 移除引号并解码 URL 编码的文件名 - filename = matches[1].replace(/['"]/g, ''); - try { - // 尝试解码 URL 编码的文件名 - filename = decodeURIComponent(filename); - } catch (e) { - console.warn('文件名解码失败,使用原始文件名'); - } - } - } - - console.log('提取的文件名:', filename); - + // 创建下载链接 const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; - // 使用获取到的文件名或本地缓存的文件名 - link.download = filename; + // 直接使用传入的 fileName + link.download = fileName; // 触发下载 document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(url); - + message.success('文件下载开始'); } catch (error) { console.error('下载失败:', error); diff --git a/apps/web/src/app/main/admin/sharecode/sharecodegenerator.tsx b/apps/web/src/app/main/admin/sharecode/sharecodegenerator.tsx index a7f8cc7..084ef48 100644 --- a/apps/web/src/app/main/admin/sharecode/sharecodegenerator.tsx +++ b/apps/web/src/app/main/admin/sharecode/sharecodegenerator.tsx @@ -6,11 +6,13 @@ import { CopyOutlined } from '@ant-design/icons'; interface ShareCodeGeneratorProps { fileId: string; onSuccess?: (code: string) => void; + fileName?: string; } export const ShareCodeGenerator: React.FC = ({ fileId, onSuccess, + fileName, }) => { const [loading, setLoading] = useState(false); const [shareCode, setShareCode] = useState(''); @@ -18,16 +20,17 @@ export const ShareCodeGenerator: React.FC = ({ const generateCode = async () => { setLoading(true); - console.log('开始生成分享码,fileId:', fileId); + console.log('开始生成分享码,fileId:', fileId, 'fileName:', fileName); try { const response = await fetch(`http://localhost:3000/upload/share/${fileId}`, { method: 'POST', - // headers: { - // 'Content-Type': 'application/json', - // }, - // body: JSON.stringify({ - // }) + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + fileId + }) }); console.log('Current fileId:', fileId); // 确保 fileId 有效 console.log('请求URL:', `/upload/share/${fileId}`); diff --git a/apps/web/src/app/main/admin/sharecode/sharecodevalidator.tsx b/apps/web/src/app/main/admin/sharecode/sharecodevalidator.tsx index e10d7ae..a973456 100644 --- a/apps/web/src/app/main/admin/sharecode/sharecodevalidator.tsx +++ b/apps/web/src/app/main/admin/sharecode/sharecodevalidator.tsx @@ -3,7 +3,7 @@ import { Input, Button, message } from 'antd'; import styles from './ShareCodeValidator.module.css'; interface ShareCodeValidatorProps { - onValidSuccess: (fileId: string) => void; + onValidSuccess: (fileId: string, fileName: string) => void; } export const ShareCodeValidator: React.FC = ({ @@ -26,10 +26,20 @@ export const ShareCodeValidator: React.FC = ({ const errorData = await response.json().catch(() => ({})); throw new Error(errorData.message || '分享码无效或已过期'); } + const data = await response.json(); - onValidSuccess(data.fileId); - message.success('验证成功'); + console.log('验证分享码返回数据:', data); + + if (!data.fileId) { + throw new Error('未找到文件ID'); + } + + const fileName = data.fileName || 'downloaded_file'; + + onValidSuccess(data.fileId, fileName); + message.success(`验证成功,文件名:${fileName}`); } catch (error) { + console.error('验证分享码失败:', error); message.error('分享码无效或已过期'); } finally { setLoading(false); diff --git a/apps/web/src/hooks/useTusUpload.ts b/apps/web/src/hooks/useTusUpload.ts index 5e2e761..490dfd4 100755 --- a/apps/web/src/hooks/useTusUpload.ts +++ b/apps/web/src/hooks/useTusUpload.ts @@ -7,9 +7,10 @@ interface UploadResult { compressedUrl: string; url: string; fileId: string; + fileName: string; } -export function useTusUpload(p0: { onSuccess: (fileId: string) => void; onError: (error: Error) => void; }) { +export function useTusUpload(p0: { onSuccess: (result: UploadResult) => void; onError: (error: Error) => void; }) { const [uploadProgress, setUploadProgress] = useState< Record >({}); @@ -87,6 +88,7 @@ export function useTusUpload(p0: { onSuccess: (fileId: string) => void; onError: compressedUrl: getCompressedImageUrl(url), url, fileId, + fileName: uploadFile.name, }); } } catch (error) {