如何在加载文件项后仅从dataTransfer调度FileList [英] How to only dispatch FileList from dataTransfer after File items are loaded

查看:168
本文介绍了如何在加载文件项后仅从dataTransfer调度FileList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个名为react-dropzone和React-Redux的Node包模块,以允许用户将文件拖到窗口上并显示文件信息。

I'm using a Node package module called react-dropzone and React-Redux to allow users to drag a file onto the window and display the file info.

react-dropzone组件为我提供了标准 event.dataTransfer.files

The react-dropzone component is giving me the FileList from the standard event.dataTransfer.files.

我遇到的问题是,当我将FileList分发到Redux存储时,File项尚未加载到FileList数组中,因此当我分发时文件数据,我只得到 { preview: blob:file:/// f30eafb8-8a77-4402-9111-379590b4a03f}

The problem I'm having is that when I dispatch that FileList to the Redux store, the File items aren't yet loaded in the FileList array, so when I dispatch the File data, I just get {"preview":"blob:file:///f30eafb8-8a77-4402-9111-379590b4a03f"}.

如果我将File项记录到控制台,它们显示得很好,因为在我查看它们时已加载了它们的数据,但我不知道如何只分派文件

If I log the File items to the console, they show up just fine because their data is loaded by the time I look at it but I can't figure out how to only dispatch the file information after it's loaded.

以下是我从FileList数组中将文件项之一记录到控制台的示例。

Here's an example of what I see if I log one of the File items to the console from the FileList array.

{
  lastModified: 1473709614000,
  lastModifiedDate: Mon Sep 12 2016 12:46:54 GMT-0700 (PDT),
  name: "test_image.jpg",
  path: "/Users/mitchconquer/Desktop/test_image.jpg",
  preview: "blob:file:///0fe69686-125d-464a-a0a8-a42e497d3808",
  size: 41805,
  type: "image/jpeg",
  webkitRelativePath: ""
}

我相信问题是File对象没有完全加载,但我想不出一种方法数据完全加载后便触发操作。有人可以指出我在正确的道路上吗?

I believe the problem is just that the File object isn't fully loaded, but I can't figure out a way to only fire the action once the data is fully loaded. Could someone point me on the right path?

这是我使用React-dropzone的组件:

Here's my component that's using react-dropzone:

// FileDrop.js
import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import styles from './Home.css';
import Dropzone from 'react-dropzone';

export default class FileDrop extends Component {
  static propTypes = {
    message: PropTypes.string.isRequired,
    setFile: PropTypes.func.isRequired
  };

  onDrop(files, event) {
    console.log({files});
    this.props.setFile(files);
  }

  render() {
    return (
      <div>
        <Dropzone onDropAccepted={this.onDrop.bind(this)} multiple={false} disablePreview={false}>
          <div>{this.props.message}</div>
        </Dropzone>
      </div>
    );
  }
}

...这是我的操作文件上面的 onDrop 方法中使用的 setFile 方法:

...and here's my action file that has the setFile method that's used in the above onDrop method:

// actions/files.js
export const SET_FILE = 'SET_FILE';

// ACTION CREATORS

function _setFile(file) {
  return {
    type: SET_FILE,
    file
  };
}

// ACTION CREATOR CREATORS

export function setFile(file) {
  return _setFile(file[0]);
}

...这是处理该操作的减速器:

...and here's the reducer that's handling that action:

// reducers/files.js
import { SET_FILE } from '../actions/files';

export const initialState = [];

export default function files(state = initialState, action = {}) {
  switch (action.type) {
    case SET_FILE:
      const newState = state.slice();
      const file = action.file;
      newState.push(file);
      return newState;
    default:
      return state;
  }
}


推荐答案

那些遇到此问题的人,对我来说,我 问题是文件列表中的文件不是我认为的普通JavaScript对象,但实际上是文件/斑点。

For those of you who are having this issue, for me I think the issue was that the Files in the Filelist weren't "plain ol' JavaScript objects" like I thought they were but in fact Files/Blobs.

我不确定这些细节-如果有人会解释,我会喜欢的-但是我想我知道什么是blob不像标准JS对象那样具有键,因此您不能仅将其推入Redux商店并查看它们的键值对(我期望的属性)( lastModified,lastModifiedDate ,名称,路径,预览,大小,类型,webkitRelativePath )。

I'm not sure of the details -- and would love it if someone would explain them -- but What I Think I Know is that the blob doesn't have keys like a standard JS object does so you can't just push it to the Redux store and see they key-value pairs of the properties I was expecting (lastModified, lastModifiedDate, name, path, preview, size, type, webkitRelativePath).

如果您仅查看Blob,则它们的唯一属性是 preview 因为这是React Dropzone在File / Blob上专门设置的属性。要查看其他属性,必须在Blob上调用每个属性。

If you just looked at the blob, they only property was the preview because that was a property specifically set on the File/Blob by React Dropzone. To see the other properties, you have to call each one on the blob.

这是下面我的解决方案的简化版本。我进入Filelist数组,创建一个新对象以设置键值并遍历每个键,并在 newFile 对象上设置其属性。最后我返回那个对象。然后,您可以在商店中设置该对象,该对象将具有处理文件所需的数据。

This is a simplified version of my solution below. I take in the Filelist array, create a new object to set the key-values on and iterate through each key and set it with its property on the newFile object. Finally I return that object. You can then set that object in your store and it will have the necessary data to work with the files.

onDrop(files) {
    const fileBlob = files[0];
    const newFile = {};
    _fileProperties.forEach(key => {
      newFile[key] = fileBlob[key];
    });

   return newFile;
}

const _fileProperties = [
  'lastModified',
  'lastModifiedDate',
  'name',
  'path',
  'preview',
  'size',
  'type',
  'webkitRelativePath'
];

可能有很多更好的方法可以做到,而且我确信我的理解已经关闭,所以我如果有人能更好地解释这一点,我还是会喜欢的。同时,此解决方案对我有用。

There are probably lots of better ways of doing this and I'm sure my understanding is off so I'd still love it if someone would explain this better. In the meantime, this solution worked for me.

还有其他一些地方,例如 MDN的文件拖放文章。

There are also some other places for more info such as MDN's File drag and drop article.

这篇关于如何在加载文件项后仅从dataTransfer调度FileList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆