1

我已经使用拖放构建了一个文件上传组件react-dropzone

我想检查文件,用户拖动到 dropzone 并在它们被拖动时执行此操作它们被拖放到 dropzone 之前)。

我试过这个:

<Dropzone
  accept="application/pdf"
  onDrop={this.handleDragDrop}
>
  {({ draggedFiles, isDragActive, isDragReject, acceptedFiles, rejectedFiles }) => {
    if (isDragActive) {
      ... inspect files here (before dropping)
    }
  }}
</Dropzone>

但非draggedFiles,acceptedFiles并且rejectedFiles有任何价值。

我在这里错过了什么......?


编辑:

为了让我的问题更清楚:

我想在用户将文件放到dragzone. 在我的场景中,通过将 mimetypes 传递给accept属性的验证还不够:

  1. 用户将文件拖过dragzone并被onDragOver解雇
  2. 现在检查文件并dragzone更新以显示消息files are ok或,因此用户在删除文件之前files not ok获取此信息
  3. 用户正在删除文件并被onDrop触发
4

4 回答 4

2

Short answer

AFAIK You can't

Long answer

Let's see the following code:

<Dropzone 
  accept="image/*,application/pdf" 
  maxSize={5000000}
  onDrop={this.onDrop}
  onDragEnter={this.onDragEnter}
>
  {({getRootProps, getInputProps, isDragAccept, isDragReject }) => {
    let classes = 'form-control'
    let placeholder = <p>Drag files here</p>;
    if (isDragAccept) {
      classes = `${classes} border-success bg-light`;
      placeholder = <p className="text-success">Drop files now</p>;
    } 
    if (isDragReject) {
      classes = `${classes} border-danger bg-light`;
      placeholder = <p className="text-danger">Some files are not allowed</p>
    }
    return (
      <div {...getRootProps()} style={{ height: '100px' }} className={classes}>
        <input {...getInputProps()} />
        {placeholder}
      </div>
    );
  }}
</Dropzone>

This snippet changes the style of the dropzone if the file to be dropped meets some requirements (any image type or pdf file and that is less than 5MB of size). If we drag any file over the dropzone the values of acceptedFiles and rejectedFiles are both an empty array. The value of draggedFiles is an array of DataTransferItems which give us the kind and type of the file being dragged, for example {kind: "file", type: "application/pdf"}.

At this point the values of isDragAccept and isDragReject are setted based on the type of the file. So, if we drag an image or a pdf file the value isDragAccept is set to true, the text Drop files now will be shown in the dropzone its border will be colored according the class border-success. But the same will occur if the file is greater than 5MB! Why? This is because we cannot read the file before the drop event.

Let see the event handlers:

onDrop = (acceptedFiles, rejectedFiles, event) => {
  console.log(event.dataTransfer.items)
  console.log(event.dataTransfer.files)
}

onDragEnter = (event) => {
  console.log(event.dataTransfer.items)
  console.log(event.dataTransfer.files)
}

The drag events give us a dataTransfer property which is a DataTransfer object. Here we have two properties that are important to us:

  • DataTransfer.items

    This is a DataTransferItemList object which give us a list of DataTransferItems. It's the same object in the draggedFiles array and we can access this in both handlers: onDragEnter and onDrop.

  • DataTransfer.files

    This holds a FileList object of the drag operation, but it's empty in the Drag events so we can access it only after the drop. For example, in the previous code if we drag and drop some file we get this output for the console log for the events showed:

FileList {length: 0} // dragEnter event
FileList {0: File(30299626), length: 1} // drop event

If we access the element 0 of the File list after the drop we get:

File(30299626) {name: "python_101.pdf", lastModified: 1549327543709, lastModifiedDate: Mon Feb 04 2019 21:45:43 GMT-0300 (Chile Summer Time), webkitRelativePath: "", size: 30299626, …}

Thus, we can only access data of the file After the drop event.

于 2019-02-08T18:10:01.593 回答
1

这样做(反应):

  onDragOverHandle(event) {
    event.stopPropagation();
    event.preventDefault();
    console.log(event.dataTransfer.items[0])
  }

您可以获得拖动目标类型,例如:

{kind: "file", type: "image/png"}或者{kind: "file", type: "video/mp4"}

然后你可以做你想做的事情。

希望能帮到你~

于 2020-01-09T10:51:49.493 回答
0

正如@Jay lu sayied,你可以使用这样的东西:

const onDragEnter = (event) => {
    const fileType = event.dataTransfer.items[0].type;
    const validTypes = ['image/png', 'image/jpeg', 'image/jpg'];
    const valitate = validTypes.some(types => types === fileType);
    !valitate && setDanger(true);
  }

const onDragLeave = (event) => {
    setDanger(false);
  }

<Dropzone
        onDrop={ onDrop }
        accept='image/jpeg, image/png, image/jpg'
        maxSize={500000}
        onDragEnter={onDragEnter}
        onDragLeave={onDragLeave}
      >
于 2021-09-17T14:40:50.117 回答
-1

您需要使用 : 初始化您的状态this.state = { files: [] }并在函数中处理放置文件:onDrop(files) { // do stuff with files... }

这是来自文档https://react-dropzone.js.org/的示例摘录:

class Basic extends React.Component {
  constructor() {
    super()
    this.state = { files: [] }
 }

 onDrop(files) {
   this.setState({
     files
   });
 }

 render() {
   return (
     <section>
    <div className="dropzone">
      <Dropzone onDrop={this.onDrop.bind(this)}>
        <p>Try dropping some files here, or click to select files to upload.</p>
      </Dropzone>
    </div>
    <aside>
      <h2>Dropped files</h2>
      <ul>
        {
          this.state.files.map(f => <li key={f.name}>{f.name} - {f.size} bytes</li>)
        }
      </ul>
    </aside>
  </section>
);
}}
于 2018-04-24T09:37:05.513 回答