158 lines
4.7 KiB
TypeScript
158 lines
4.7 KiB
TypeScript
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];
|
||
}
|