2016-10-26 4 views
1

私は、ユーザーがファイルをウィンドウにドラッグしてファイル情報を表示できるように、react-dropzoneとReact-Reduxというノードパッケージモジュールを使用しています。ファイルアイテムがロードされた後でのみ、dataTransferからFileListをディスパッチする方法

react-dropzoneコンポーネントが私に標準event.dataTransfer.filesのFileListを与えています。

RedListストアにFileListをディスパッチすると、FileList配列にFileアイテムがまだロードされていないので、Fileデータを送出するときには、{"preview":"blob:file:///f30eafb8-8a77-4402-9111-379590b4a03f"}が返されます。

ファイル項目をコンソールに記録すると、データが表示されるまでにデータが読み込まれるため、表示されますが、読み込まれた後にファイル情報をディスパッチする方法がわかりません。

FileList配列からFile項目の1つをコンソールに記録すると、次のような結果が表示されます。

{ 
    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オブジェクトが完全にロードされていないだけということであると信じていますが、データが完全にロードされたら、私は唯一のアクションを発射する方法を把握することはできません。誰かが正しい道を私に指摘することができますか?

は、ここで反応し、ドロップゾーンを使っている私のコンポーネントです:

// 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方法を持っている私のアクションファイルです:

// 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]); 
} 

..そして、そのアクションを扱っている減速機があります:

// 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; 
    } 
} 

答えて

1

この問題を抱えている人のために私のためにだと思うのですが、ファイルリスト内のファイルは実際にはファイル/ブロブだと思ったように「普通のJavaScriptオブジェクト」ではないということでした。

私は詳細を誰かが説明すれば好きですが、私が知っていると思うもの BLOBには標準のJSオブジェクトのようなキーはありませんそれをReduxストアにプッシュして、私が期待していたプロパティのキーと値のペアを確認することはできません(lastModified, lastModifiedDate, name, path, preview, size, type, webkitRelativePath)。

ブロブを見ただけでは、それはpreviewでした。これは、ファイル/ Blob by React Dropzoneに特別に設定されたプロパティだったからです。他のプロパティを見るには、ブロブのそれぞれを呼び出す必要があります。

これは私のソリューションの簡略化されたバージョンです。私はFilelist配列を取り込み、キー値を設定するための新しいオブジェクトを作成し、各キーを繰り返し処理し、そのプロパティをnewFileオブジェクトに設定します。最後にそのオブジェクトを返します。そのオブジェクトをストアに設定すると、ファイルで作業するために必要なデータが作成されます。

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' 
]; 

は、おそらくこれを行うのより良い方法はたくさんありますし、私は私の理解は、誰かがこの良く説明するだろう場合ので、私はまだそれを愛するだろうオフになっていると確信しています。その間、このソリューションは私のために働いた。

MDN's File drag and dropのような詳細については、他の場所もあります。

+0

ロダッシュを使用している場合は、「_.toPlainObject(files [0])」を実行することもできます。 –

0

私は同じ問題がありました。 @Ishmael Smyrnowが作った@Mitch Conquerとコメントによって提供されるソリューションを試しましたが、Fileオブジェクトではなくプレーンオブジェクトを返します。また、hereで説明したように、直列化不可能なオブジェクトをストアに格納することはお勧めしません。したがって、私がやったのは、最初にFile64を使ってファイルをbase64に変換して保存したことです。

const reader = new FileReader(); 
reader.readAsDataURL(file); 

そして、hereによって提供される解決策としてファイルに変換された後。

export const dataURLtoFile = (dataurl, filename) => { 
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], 
    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); 
    while(n--){ 
     u8arr[n] = bstr.charCodeAt(n); 
    } 
    return new File([u8arr], filename, {type:mime}); 
} 
関連する問題