In React-dropzone, how to tell the user the file's maxSize is too big?
Asked Answered
O

3

8

I am using the following to allow a user to upload a profile photo with 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>
  );
}

... inside my redux-form:

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

React-dropzone is currently respecting the maxSize, where it rejects files that are over 5megs. The problem is react-dropzone is not telling the user the file is too big.

How can I update the above to tell the user if the file exceeds the maxSize allowed?

Oscilloscope answered 26/6, 2017 at 1:11 Comment(0)
A
12
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. Create a useState for errors as above.

  2. onDrop provides a second array argument 'fileRejections'.

  3. Loop through fileRejections to access the errors array in it.

  4. Then, loop through the errors array to access 'code and 'message'.

  5. Check the error code with if else for 'file-too-large' or 'file-invalid-type'. Which are the most common error codes.

  6. Use setState in the if else block to set the err.message to the error state.

  7. Display the error state in 'p' tags inside your dropzone's main div.

This works very well when multiple is set 'false'. For multiple file errors you will have to use an arrayState I guess. I haven't really looked into it.

Artie answered 5/9, 2020 at 11:2 Comment(2)
Where do you specify the accepted formats and size here?Mitman
I am not too sure if I understood the question properly. But, this link may be of use to you. react-dropzone.org/#!/Accepting%20specific%20file%20typesArtie
S
1

you can have the current size for every file after loaded, and compare with your constant. i don't know if file has a size props, but i suppose that it's included in props. Code should looks like:

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>
  );
}
Socialist answered 14/12, 2017 at 7:28 Comment(0)
W
-2

wherever you are saving your file just add .size dropzone gives size in bytes divide it with 1000000 if ans is 1 then show your error. mainly .size property will do your job

Whistling answered 15/11, 2023 at 13:19 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Perfect

© 2022 - 2024 — McMap. All rights reserved.