4

我正在使用以下内容允许用户使用react-dropzone上传个人资料照片:

const FILE_FIELD_NAME = 'files';

const renderDropzoneInput = (field) => {
  const files = field.input.value;
  let dropzoneRef;
  return (
    <div>
      <Dropzone
        name={field.name}
        onDrop={( filesToUpload, e ) => field.input.onChange(filesToUpload)}
        ref={(node) => { dropzoneRef = node; }}
        accept="image/jpeg, image/png"
        maxSize={5242880}
      >
        {({ isDragActive, isDragReject, acceptedFiles, rejectedFiles }) => {
          if (isDragActive) {
            return "This file is authorized";
          }
          if (isDragReject) {
            return "This file is not authorized";
          }
          return acceptedFiles.length || rejectedFiles.length
            ? `Accepted ${acceptedFiles.length}, rejected ${rejectedFiles.length} files`
            : "Try dropping some files.";
        }}
      </Dropzone>

      <button type="button" onClick={() => { dropzoneRef.open() }}>Open File Dialog</button>

      {field.meta.touched &&
        field.meta.error &&
        <span className="error">{field.meta.error}</span>}
      {
        files && Array.isArray(files) && (
        <ul>
          { files.map((file, i) =>
            <li key={i}>
              <img key={i} style={{width: 50, height: 50}} src={file.preview} alt="preview" />
              {file.name}
            </li>
          )}
        </ul>
      )}
    </div>
  );
}

...在我的 redux-form 中:

    <div>
      <label htmlFor={FILE_FIELD_NAME}>Files</label>
      <Field
        name={FILE_FIELD_NAME}
        component={renderDropzoneInput}
      />
    </div>

React-dropzone 当前尊重 maxSize,它拒绝超过 5megs 的文件。问题是 react-dropzone 没有告诉用户文件太大。

如何更新上述内容以告诉用户文件是否超过允许的 maxSize?

4

2 回答 2

7
import React, { useState } from "react";
import { useDropzone } from "react-dropzone";

const UploadFile = () => {
  const [errors, setErrors] = useState("");

  const { getRootProps, getInputProps } = useDropzone({
    multiple: false,
    onDrop: (acceptedFiles, fileRejections) => {
      fileRejections.forEach((file) => {
        file.errors.forEach((err) => {
          if (err.code === "file-too-large") {
            setErrors(`Error: ${err.message}`);
          }

          if (err.code === "file-invalid-type") {
            setErrors(`Error: ${err.message}`);
          }
        });
      });
    }

  return (
    <div{...getRootProps()}>
      <input {...getInputProps()} title={title} />
        <p style={{ color: "red", padding: 5, margin: 0, fontSize: 14 }}>
          {errors}
        </p>
    </div>
  );
};
  1. 如上所述为错误创建一个 useState。

  2. onDrop 提供了第二个数组参数“fileRejections”。

  3. 循环访问 fileRejections 以访问其中的错误数组。

  4. 然后,循环遍历错误数组以访问“代码”和“消息”。

  5. 使用 if else 检查错误代码是否为 'file-too-large' 或 'file-invalid-type'。哪些是最常见的错误代码。

  6. 在 if else 块中使用 setState 将 err.message 设置为错误状态。

  7. 在 dropzone 的主 div 内的“p”标签中显示错误状态。

当多个设置为“假”时,这非常有效。对于多个文件错误,我猜您将不得不使用 arrayState。我还没有真正研究过。

于 2020-09-05T11:02:31.770 回答
0

您可以在加载后获得每个文件的当前大小,并与您的常量进行比较。我不知道文件是否有大小道具,但我想它包含在道具中。代码应如下所示:

const FILE_FIELD_NAME = 'files';

const ErrorMessage = ({ children }) => (
  <div
    style={{
      fontStyle: 'italic',
      color: 'red',
      }}
    >
    {children}
  </div>
)

const renderDropzoneInput = (field) => {
  const files = field.input.value;
  let dropzoneRef;
  const MAX_SIZE = 5242880;
  return (
    <div>
      <Dropzone
        name={field.name}
        onDrop={( filesToUpload, e ) => field.input.onChange(filesToUpload)}
        ref={(node) => { dropzoneRef = node; }}
        accept="image/jpeg, image/png"
        maxSize={MAX_SIZE}
      >
        {({ isDragActive, isDragReject, acceptedFiles, rejectedFiles }) => {
          if (isDragActive) {
            return "This file is authorized";
          }
          if (isDragReject) {
            return "This file is not authorized";
          }
          return acceptedFiles.length || rejectedFiles.length
            ? `Accepted ${acceptedFiles.length}, rejected ${rejectedFiles.length} files`
            : "Try dropping some files.";
        }}
      </Dropzone>

      <button type="button" onClick={() => { dropzoneRef.open() }}>Open File Dialog</button>

      {field.meta.touched &&
        field.meta.error &&
        <span className="error">{field.meta.error}</span>}
      {
        files && Array.isArray(files) && (
        <ul>
          { files.map((file, i) =>
            <li key={i}>
              {file.size > MAX_SIZE ?  (
                  <ErrorMessage>
                    {'file is too big, try with another file'}
                    {file.name}
                  </ErrorMessage>
                ) : (
                  <React.fragment>
                    <img key={i} style={{width: 50, height: 50}} src={file.preview} alt="preview" />
                    {file.name}
                  </React.fragment>
                ) 
              }
            </li>
          )}
        </ul>
      )}
    </div>
  );
}
于 2017-12-14T07:28:41.153 回答