S3DownloadButton.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import React, { useState } from 'react';
  2. import {
  3. Button,
  4. TextField,
  5. Box,
  6. Typography,
  7. Alert,
  8. } from '@mui/material';
  9. import { Download } from '@mui/icons-material';
  10. interface S3DownloadButtonProps {
  11. label?: string;
  12. }
  13. const S3DownloadButton: React.FC<S3DownloadButtonProps> = ({ label = 'S3下载' }) => {
  14. const [fileName, setFileName] = useState('');
  15. const [error, setError] = useState('');
  16. const [success, setSuccess] = useState('');
  17. const handleDownload = async () => {
  18. if (!fileName.trim()) {
  19. setError('请输入文件名');
  20. return;
  21. }
  22. try {
  23. setError('');
  24. setSuccess('');
  25. // 构建S3文件URL
  26. const fileUrl = `http://172.14.3.142:4566/my-bucket/uploads/${fileName.trim()}`;
  27. // 方法1:直接使用a标签下载(如果S3配置了正确的Content-Disposition)
  28. const link = document.createElement('a');
  29. link.href = fileUrl;
  30. link.download = fileName.trim();
  31. link.target = '_blank';
  32. // 方法2:如果方法1不行,尝试添加时间戳避免缓存问题
  33. // const timestamp = new Date().getTime();
  34. // const downloadUrl = `${fileUrl}?t=${timestamp}`;
  35. // link.href = downloadUrl;
  36. // 添加到DOM并触发点击
  37. document.body.appendChild(link);
  38. link.click();
  39. document.body.removeChild(link);
  40. setSuccess(`文件 ${fileName} 下载成功!`);
  41. setFileName('');
  42. } catch (err) {
  43. setError(`下载失败: ${err instanceof Error ? err.message : '未知错误'}`);
  44. }
  45. };
  46. const handleKeyPress = (event: React.KeyboardEvent) => {
  47. if (event.key === 'Enter') {
  48. handleDownload();
  49. }
  50. };
  51. return (
  52. <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, p: 2, border: '1px solid #e0e0e0', borderRadius: 1 }}>
  53. <Typography variant="h6" gutterBottom>
  54. S3文件下载
  55. </Typography>
  56. <Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
  57. <TextField
  58. label="文件名"
  59. variant="outlined"
  60. size="small"
  61. value={fileName}
  62. onChange={(e) => setFileName(e.target.value)}
  63. onKeyPress={handleKeyPress}
  64. placeholder="例如: 20251125_150429_f43f9a67.txt"
  65. sx={{ minWidth: 300 }}
  66. />
  67. <Button
  68. variant="contained"
  69. startIcon={<Download />}
  70. onClick={handleDownload}
  71. disabled={!fileName.trim()}
  72. >
  73. {label}
  74. </Button>
  75. </Box>
  76. {error && (
  77. <Alert severity="error" onClose={() => setError('')}>
  78. {error}
  79. </Alert>
  80. )}
  81. {success && (
  82. <Alert severity="success" onClose={() => setSuccess('')}>
  83. {success}
  84. </Alert>
  85. )}
  86. <Typography variant="body2" color="text.secondary">
  87. 提示:输入文件名后点击下载按钮,文件将从S3存储桶下载到本地
  88. </Typography>
  89. </Box>
  90. );
  91. };
  92. export default S3DownloadButton;