如何知道从特定文件扩展名中拖动的文件?

时间:2019-04-23 18:23:05

标签: javascript reactjs

我正在创建自己的拖放区,并且想在拖动特定文件扩展名时执行操作,我发现onDragEnter无法访问文件类型,onDrop仅能做到这一点。

但是我找到了一个可以做我想做的东西的库,我试图从源代码中知道他们是怎么做的,但是我失败了。这是代码的链接

https://react-dropzone.netlify.com/#!/Accepting%20specific%20file%20types/5

2 个答案:

答案 0 :(得分:0)

实际上文件类型可用,我不知道dropzone是如何反应的,但是您可以通过DragEvent.dataTransfer.items[0].type访问该类型,items是要拖动的项目数组,因此您可以访问其他人则通过items[1]

$('div').on('dragover',function(e){
console.log(e.originalEvent.dataTransfer.items[0].type);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>dropzone</div>

答案 1 :(得分:0)

好吧,onDragEnter没有为您提供此信息,但是您可以从onDragOver获得该信息。

要使用React做到这一点,我想最简单的方法是使用ref回调将元素放入您要放置的位置(或直接使用该元素上的事件)。

setTargetDropZone( element ) {
  if (this.dropZone) {
    // remove any previous attached event
    this.dropZone.removeEventListener('dragover', this.onDragOver );
  }
  // update the local field with the new element
  this.dropZone = element;
  if (!this.dropZone) {
    return;
  }
  // if it is not null attach the new event
  this.dropZone.addEventListener( 'dragover', this.onDragOver );
}

在某些地方,您必须定义要接受的文件类型,然后必须处理传入的数据以对其进行过滤。

const { fileTypes = null } = this.props;
const { items } = e.dataTransfer;
let dropCount = items.length;

// if it is restricted, count how many actually match
if (fileTypes) {
  // items is not an array, so you could use Array.from here
  dropCount = Array.from( items ).filter( item => fileTypes.some( type => item.type.includes( type ) ) ).length;
}

因此,如果您结合使用此代码,最终可能会得到类似这样的结果

const { Component } = React;

const DropState = {
  'All': '0',
  'No': '1',
  'Some': '2',
  '0': 'All',
  '1': 'No',
  '2': 'Some'
};

class DropZone extends Component {
  constructor() {
    super();
    this.state = {
      dropState: DropState.All,
      dropCount: 0
    };
    this.setTargetDropZone = this.setTargetDropZone.bind( this );
  }
  onDragOver = e => {
    const { fileTypes = null } = this.props;
    const { items } = e.dataTransfer;
    let dropCount = items.length;
    
    if (fileTypes) {
      dropCount = Array.from( items ).filter( item => fileTypes.some( type => item.type.includes( type ) ) ).length;
    }
  
    this.setState( {
      dropCount,
      dropState: dropCount === items.length ? DropState.All : dropCount === 0 ? DropState.No : DropState.Some
    } );
  } 
  setTargetDropZone( element ) {
    if (this.dropZone) {
      this.dropZone.removeEventListener('dragover', this.onDragOver );
    }
    this.dropZone = element;
    if (!this.dropZone) {
      return;
    }
    this.dropZone.addEventListener( 'dragover', this.onDragOver );
  }
  render() {
    const { dropState, dropCount } = this.state;
    const { placeholder = 'Drop some files here' } = this.props;
    
    return (
      <div ref={this.setTargetDropZone} style={{border: 'solid #a0a0a0 1px' }}>
      { dropCount > 0 && <span>{ `${DropState[dropState]} will be accepted (${dropCount})` }</span> }
      { dropCount === 0 && placeholder }
      </div>
    );
  }
}

const container = document.querySelector('#container');

ReactDOM.render( <DropZone fileTypes={ ['image/jpg', 'image/jpeg', 'image/png' ] } />, container );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container">
</div>