3种场景搞定umi文件上传:从基础表单到高级拖拽

3种场景搞定umi文件上传:从基础表单到高级拖拽

【免费下载链接】umi A framework in react community ✨ 【免费下载链接】umi 项目地址: https://gitcode.com/gh_mirrors/umi8/umi

你还在为umi项目中的文件上传功能头疼吗?无论是简单的表单上传、炫酷的拖拽上传,还是需要实时进度显示的大文件上传,本文都能帮你一网打尽。读完你将掌握:基础表单上传实现、拖拽上传组件开发、大文件分片上传方案,以及完整的错误处理机制。

基础表单上传实现

核心代码实现

在umi项目中实现基础文件上传,首先需要创建一个包含文件输入框的表单。在pages目录下新建UploadPage.js文件:

import { useState } from 'react';
import { Button, message } from 'antd';

export default () => {
  const [fileList, setFileList] = useState([]);
  
  const handleFileChange = (e) => {
    const file = e.target.files[0];
    if (!file) return;
    
    setFileList([file]);
    
    const formData = new FormData();
    formData.append('file', file);
    
    // 上传逻辑
    fetch('/api/upload', {
      method: 'POST',
      body: formData,
    })
    .then(response => response.json())
    .then(data => {
      message.success('上传成功');
    })
    .catch(error => {
      message.error('上传失败');
    });
  };
  
  return (
    <div>
      <input 
        type="file" 
        onChange={handleFileChange} 
        style={{ display: 'none' }} 
        id="fileInput"
      />
      <Button onClick={() => document.getElementById('fileInput').click()}>
        选择文件上传
      </Button>
    </div>
  );
};

配置代理解决跨域

为避免跨域问题,需要在config/config.js中配置代理:

export default {
  proxy: {
    '/api': {
      target: 'http://your-server.com',
      changeOrigin: true,
      pathRewrite: { '^/api': '' },
    },
  },
};

详细配置说明可参考官方文档:config.md

拖拽上传组件开发

拖拽区域实现

利用HTML5的拖放API,可以实现拖拽上传功能。创建components/DragUpload.js组件:

import { useState } from 'react';
import { Upload, message } from 'antd';
import { InboxOutlined } from '@ant-design/icons';

const { Dragger } = Upload;

export default () => {
  const [uploading, setUploading] = useState(false);
  
  const props = {
    name: 'file',
    action: '/api/upload',
    headers: {
      authorization: 'authorization-text',
    },
    onChange(info) {
      if (info.file.status !== 'uploading') {
        console.log(info.file, info.fileList);
      }
      if (info.file.status === 'done') {
        message.success(`${info.file.name} 文件上传成功`);
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} 文件上传失败`);
      }
    },
  };
  
  return (
    <Dragger {...props}>
      <p className="ant-upload-drag-icon">
        <InboxOutlined />
      </p>
      <p className="ant-upload-text">点击或拖拽文件到此处上传</p>
      <p className="ant-upload-hint">
        支持单个或批量上传,严禁上传公司敏感文件
      </p>
    </Dragger>
  );
};

在页面中使用拖拽组件

在之前创建的UploadPage.js中引入拖拽组件:

import DragUpload from '../components/DragUpload';

export default () => {
  return (
    <div>
      <h2>基础表单上传</h2>
      {/* 之前的表单上传代码 */}
      
      <h2>拖拽上传</h2>
      <DragUpload />
    </div>
  );
};

大文件分片上传方案

分片上传核心逻辑

对于大文件,我们需要实现分片上传功能。创建utils/upload.js工具函数:

export const chunkUpload = async (file, chunkSize = 2 * 1024 * 1024) => {
  const fileId = Date.now().toString();
  const totalChunks = Math.ceil(file.size / chunkSize);
  const uploadPromises = [];
  
  for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);
    
    const formData = new FormData();
    formData.append('file', chunk);
    formData.append('fileId', fileId);
    formData.append('chunkIndex', i);
    formData.append('totalChunks', totalChunks);
    formData.append('fileName', file.name);
    
    uploadPromises.push(
      fetch('/api/upload/chunk', {
        method: 'POST',
        body: formData,
      }).then(res => res.json())
    );
  }
  
  await Promise.all(uploadPromises);
  
  // 通知服务器合并分片
  return fetch('/api/upload/merge', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ fileId, fileName: file.name }),
  }).then(res => res.json());
};

进度显示实现

结合umi的request库和进度条组件,可以实现上传进度显示:

import { Upload, Progress } from 'antd';
import { chunkUpload } from '../utils/upload';

export default () => {
  const [progress, setProgress] = useState(0);
  
  const handleUpload = async (file) => {
    await chunkUpload(file, (percent) => {
      setProgress(percent);
    });
    return false;
  };
  
  return (
    <div>
      <Upload beforeUpload={handleUpload}>
        <Button>大文件分片上传</Button>
      </Upload>
      {progress > 0 && <Progress percent={progress} />}
    </div>
  );
};

错误处理与最佳实践

完整错误处理机制

在实际项目中,需要处理各种可能的上传错误:

const handleUpload = async (file) => {
  try {
    setUploading(true);
    await chunkUpload(file);
    message.success('上传成功');
  } catch (error) {
    if (error.message.includes('网络错误')) {
      message.error('网络异常,请检查网络连接');
    } else if (error.message.includes('文件过大')) {
      message.error('文件超过最大限制,请上传小于100MB的文件');
    } else {
      message.error('上传失败,请稍后重试');
    }
  } finally {
    setUploading(false);
  }
  return false;
};

项目结构与文件组织

推荐的文件上传相关代码组织方式:

src/
├── components/
│   ├── DragUpload.js        // 拖拽上传组件
│   └── FileUploader.js      // 通用上传组件
├── pages/
│   └── UploadPage.js        // 上传功能页面
└── utils/
    └── upload.js            // 上传工具函数

更多项目结构规范可参考官方文档:app-structure.md

总结与扩展

本文介绍了umi项目中三种常见的文件上传场景:基础表单上传、拖拽上传和大文件分片上传。通过这些方案,你可以满足大多数项目的文件上传需求。在实际开发中,还可以根据需要扩展功能,如文件格式验证、上传速度限制、断点续传等。

如果你有更复杂的上传需求,可以考虑集成第三方上传服务,如阿里云OSS、腾讯云COS等,它们提供了更完善的上传解决方案和更可靠的存储服务。

希望本文对你有所帮助,如果你有任何问题或更好的解决方案,欢迎在评论区留言讨论。别忘了点赞、收藏本文,关注作者获取更多umi开发技巧!

下期预告:umi中实现文件预览功能,支持多种文件格式在线查看。

【免费下载链接】umi A framework in react community ✨ 【免费下载链接】umi 项目地址: https://gitcode.com/gh_mirrors/umi8/umi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值