我使用名为react-dropzone和React-Redux的Node包模块,允许用户将文件拖到窗口上并显示文件信息。
react-dropzone组件给出了标准event.dataTransfer.files的FileList。
我遇到的问题是,当我将FileList分派到Redux存储时,File项目尚未加载到FileList数组中,因此当我调度File数据时,我只是得到{ {1}}。
如果我将文件项目记录到控制台,它们会显示正常,因为我看到它时会加载它们的数据,但我无法弄清楚如何仅在文件信息发送后#39 ; s。装载。
以下是我从FileList数组中将其中一个文件项目记录到控制台时所看到的示例。
{"preview":"blob:file:///f30eafb8-8a77-4402-9111-379590b4a03f"}
我认为问题只是File对象没有完全加载,但我无法找到一种只在数据完全加载后触发动作的方法。有人能指出我在正确的道路上吗?
这是我的组件使用react-dropzone:
{
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: ""
}
...这里是我的操作文件,其中包含// 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>
);
}
}
方法中使用的setFile
方法:
onDrop
...这里是处理该行动的减速机:
// 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]);
}
答案 0 :(得分:1)
对于那些遇到此问题的人,对我来说,认为问题是文件列表中的文件不是&#34;普通的&#39; JavaScript对象&#34;就像我以为它们实际上是文件/ Blob。
我不确定细节 - 并且如果有人会解释它们会喜欢它 - 但我认为我知道的是blob没有钥匙就像标准的JS对象一样,你不能只是将它推送到Redux商店,看看他们所期望的属性的键值对(lastModified, lastModifiedDate, name, path, preview, size, type, webkitRelativePath
)。
如果您只是查看了blob,那么它们只有preview
属性,因为这是React Dropzone在File / Blob上专门设置的属性。要查看其他属性,您必须在blob上调用每个属性。
这是我的解决方案的简化版本。我接受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文章。
答案 1 :(得分:0)
我有同样的问题。我尝试了@Mitch Conquer提供的解决方案和@Ishmael Smyrnow的评论,但它返回普通对象而不是File对象。同样如here所述,不建议在商店中存储不可序列化的对象。因此,我所做的是,首先将文件转换为base64并使用FileReader存储。
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});
}
答案 2 :(得分:0)
我调整了func scrollViewDidScroll(_ scrollView: UIScrollView) {
let yPos = scrollView.contentOffset.y
if yPos < 0 {
let scaleX = ((yPos * -1) / 200) + 1
let translateY = yPos / 2
var commonTransform = CGAffineTransform.identity
commonTransform = commonTransform.translatedBy(x: 0, y: translateY)
commonTransform = commonTransform.scaledBy(x: scaleX, y: scaleX)
self.customView?.transform = commonTransform
}else{
self.customView?.transform = CGAffineTransform.identity
}
}
属性,如下所示:onDrop
,并将文件属性添加到我的方法中 - 这对我有用。
我认为上述原因并不是很有效,因为我的组件中还有其他输入元素 - 文件上传只是我正在捕获的一部分。
希望这有帮助!