You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js+TS项目中使用React-Dropzone如何拒绝超大文件上传

报错根因

你当前的报错来自两个逻辑遗漏:

  • 配置maxSize拦截规则后,超大文件不会进入acceptedFiles列表,此时acceptedFiles是空数组,你直接取acceptedFiles[0]执行上传逻辑,会触发空值访问错误。
  • 没有实现拒绝文件的处理分支,文件被规则拦截后没有对应的提示和逻辑兜底。
正确实现方案

react-dropzone的onDropRejected会在文件不符合配置规则(大小超限、格式不匹配、数量超限)时触发,你可以在这个回调里统一处理拦截提示,同时补全接受文件分支的边界判断即可。
具体修改点:

  1. 新增错误提示状态,存储拦截后的文案
  2. 实现onDropRejected回调,解析被拒绝文件的错误类型,返回对应提示
  3. 补全handleDrop的边界判断,acceptedFiles为空时直接终止逻辑,避免空值报错
  4. 在UI区域补充错误提示的展示位置

修改后的完整代码如下:

import { useState, useEffect, useCallback } from 'react';
import Dropzone from 'react-dropzone';
import classNames from 'classnames';
// 保留你项目中原有的Icon、AssetApis、AssetResourceType等导入

type Props = {
  name?: string;
  isError?: boolean;
  onChange?: (id: string) => void;
};

// 抽离上传限制常量,方便后续维护
const MAX_FILE_SIZE = 30000000;
const ACCEPT_FILE_TYPES = ['image/*', 'text/csv'];

export const FileUploader = ({ name, isError, onChange }: Props) => {
  const [uploading, setUploading] = useState(false);
  const [nameFile, setNameFile] = useState<string>('File format: CSV/Image, Maximum upload size: 30MB');
  const [currId, setCurrId] = useState('');
  // 新增错误提示状态
  const [errorTip, setErrorTip] = useState('');

  useEffect(() => {
    name && setNameFile(name);
  }, [name]);

  // 处理不符合规则的被拒绝文件
  const handleDropRejected = useCallback((rejectedFiles: Array<{file: File, errors: Array<{code: string, message: string}>}>) => {
    setErrorTip('');
    const firstRejectFile = rejectedFiles[0];
    if (!firstRejectFile) return;

    // 根据错误码返回对应提示文案
    const firstError = firstRejectFile.errors[0];
    switch (firstError.code) {
      case 'file-too-large':
        setErrorTip('文件大小超过30MB限制,请重新选择文件');
        break;
      case 'file-invalid-type':
        setErrorTip('不支持当前文件格式,仅支持CSV和图片文件');
        break;
      default:
        setErrorTip('文件不符合上传要求,请重新选择');
    }
  }, []);

  const handleDrop = useCallback(async (acceptedFiles: File[]) => {
    setErrorTip('');
    // 边界判断:无符合要求的文件直接终止逻辑,避免空值报错
    if (acceptedFiles.length === 0) return;

    setUploading(true);
    const file = acceptedFiles[0];
    try {
      const res = await AssetApis.create(file, AssetResourceType.marketingAction);
      if (res.id) {
        setNameFile(file.name);
        onChange?.(res.id);
        currId && (await AssetApis.remove(currId));
        setCurrId(res.id);
      }
    } catch (err) {
      setErrorTip('文件上传失败,请重试');
    } finally {
      setUploading(false);
    }
  }, [currId, onChange]);

  return (
    <div>
      <Dropzone
        onDrop={handleDrop}
        onDropRejected={handleDropRejected}
        multiple={false}
        accept={ACCEPT_FILE_TYPES}
        disabled={uploading}
        maxSize={MAX_FILE_SIZE}>
        {({ getRootProps, getInputProps }) => (
          <div
            {...getRootProps({ className: 'dropzone' })}
            className='flex items-center w-full h-40 text-center'>
            <input {...getInputProps()} />
            <div
              className={classNames(
                'rounded flex h-full items-center justify-center flex-col flex-1 border border-dashed text-gray-700 mr-2.5 py-6',
                isError || errorTip ? 'border-danger' : 'border-gray'
              )}>
              <Icon name='upload' size={20} />
              <div className='mb-2.5 text-medium'>Drag and drop to upload</div>
              <button
                type='button'
                className='px-2.5 border-gray-700 border rounded-full text-small px-3 py-0.5'>
                Select file
              </button>
              <div className='mt-2 text-gray-500 text-small'>{nameFile}</div>
              {/* 错误提示展示位 */}
              {errorTip && <div className='mt-1 text-danger text-small'>{errorTip}</div>}
            </div>
          </div>
        )}
      </Dropzone>
    </div>
  );
};
补充说明
  • 如果你使用的是v14及以上版本的react-dropzone,accept属性需要传入MIME类型映射对象格式,旧版本的数组写法会触发警告,可根据实际安装版本调整。
  • 回调函数建议用useCallback包裹,避免子组件不必要的重渲染。
  • 上传逻辑增加了try/catch/finally包裹,避免接口报错时loading状态一直卡住无法重置。

内容的提问来源于stack exchange,提问作者KYin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 03:54:23