fenghuo/apps/web/components/FileDownload.tsx

158 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from 'react';
import { useTusUpload } from '../hooks/useTusUpload';
interface FileDownloadProps {
fileId?: string;
fileName?: string;
className?: string;
}
export function FileDownload({ fileId, fileName, className }: FileDownloadProps) {
const { getFileUrlByFileId, getFileInfo } = useTusUpload();
const [inputFileId, setInputFileId] = useState(fileId || '');
const [fileInfo, setFileInfo] = useState<any>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// 获取文件信息
const handleGetFileInfo = async () => {
if (!inputFileId.trim()) {
setError('请输入文件ID');
return;
}
setLoading(true);
setError(null);
try {
const info = await getFileInfo(inputFileId);
if (info) {
setFileInfo(info);
} else {
setError('文件不存在或未准备好');
}
} catch (err) {
setError('获取文件信息失败');
} finally {
setLoading(false);
}
};
// 直接下载文件
const handleDirectDownload = () => {
const downloadUrl = getFileUrlByFileId(inputFileId);
window.open(downloadUrl, '_blank');
};
// 复制下载链接
const handleCopyLink = async () => {
const downloadUrl = getFileUrlByFileId(inputFileId);
try {
await navigator.clipboard.writeText(downloadUrl);
alert('下载链接已复制到剪贴板!');
} catch (error) {
console.error('复制失败:', error);
}
};
// 在新窗口预览文件
const handlePreview = () => {
const downloadUrl = getFileUrlByFileId(inputFileId);
window.open(downloadUrl, '_blank');
};
return (
<div className={`p-6 bg-white rounded-lg shadow-md ${className || ''}`}>
<h3 className="text-lg font-semibold mb-4"></h3>
{/* 文件ID输入 */}
<div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-2">ID</label>
<div className="flex gap-2">
<input
type="text"
value={inputFileId}
onChange={(e) => setInputFileId(e.target.value)}
placeholder="输入文件ID"
className="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
onClick={handleGetFileInfo}
disabled={loading}
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50"
>
{loading ? '查询中...' : '查询'}
</button>
</div>
</div>
{/* 错误信息 */}
{error && <div className="mb-4 p-3 bg-red-100 border border-red-300 text-red-700 rounded-md">{error}</div>}
{/* 文件信息 */}
{fileInfo && (
<div className="mb-6 p-4 bg-gray-50 rounded-md">
<h4 className="font-medium mb-2"></h4>
<div className="space-y-1 text-sm">
<p>
<span className="font-medium">:</span> {fileInfo.title || '未知'}
</p>
<p>
<span className="font-medium">:</span> {fileInfo.type || '未知'}
</p>
<p>
<span className="font-medium">:</span> {fileInfo.status || '未知'}
</p>
{fileInfo.meta?.size && (
<p>
<span className="font-medium">:</span> {formatFileSize(fileInfo.meta.size)}
</p>
)}
<p>
<span className="font-medium">:</span> {new Date(fileInfo.createdAt).toLocaleString()}
</p>
</div>
</div>
)}
{/* 操作按钮 */}
{inputFileId && (
<div className="flex gap-2 flex-wrap">
<button
onClick={handleDirectDownload}
className="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700"
>
</button>
<button onClick={handlePreview} className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
/
</button>
<button onClick={handleCopyLink} className="px-4 py-2 bg-gray-600 text-white rounded-md hover:bg-gray-700">
</button>
</div>
)}
{/* 使用说明 */}
<div className="mt-6 p-4 bg-blue-50 rounded-md">
<h4 className="text-sm font-medium text-blue-900 mb-2">使</h4>
<ul className="text-xs text-blue-700 space-y-1">
<li> ID后点击"查询"</li>
<li> "直接下载"</li>
<li> "预览/查看"PDF等可预览的文件</li>
<li> "复制链接"</li>
</ul>
</div>
</div>
);
}
// 格式化文件大小
function formatFileSize(bytes: number): string {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}