使用DropzoneJS时获取文件内容

时间:2015-11-14 16:48:10

标签: dropzone.js

我真的很喜欢DropZoneJS组件,目前正将它包装在EmberJS组件中(您可以看到demo here)。在任何情况下,包装器工作得很好,但我想收听Dropzone的一个事件并内省文件内容(不是像meta,lastModified等元信息)。我正在处理的文件类型是一个XML文件,我想在发送之前查看它以进行验证。

怎么能这样做?我原本以为内容会挂在file对象上,你可以在许多事件中找到它,但除非我只是遗漏了一些明显的东西,否则它就不存在了。 :(

3 个答案:

答案 0 :(得分:14)

这对我有用:

Dropzone.options.PDFDrop = {
    maxFilesize: 10, // Mb
    accept: function(file, done) {
        var reader = new FileReader();
        reader.addEventListener("loadend", function(event) { console.log(event.target.result);});
        reader.readAsText(file);
    }
};
如果是二进制数据,

也可以使用reader.reaAsBinaryString()

答案 1 :(得分:6)

好的,我已经回答了我自己的问题,而且由于其他人似乎感兴趣,我会在这里发布我的答案。有关此工作演示,您可以在此处找到它:

  

https://ui-dropzone.firebaseapp.com/demo-local-data

在演示中,我将Dropzone组件包装在EmberJS框架中,但是如果你查看代码,你会发现它只是Javascript代码,没什么好害怕的。 :)

我们要做的事情是:

  • 在网络请求之前获取文件

    我们需要熟悉的关键是HTML5 API。好消息是它很简单。看看这段代码,也许就是你所需要的:

    /**
     * Replaces the XHR's send operation so that the stream can be
     * retrieved on the client side instead being sent to the server.
     * The function name is a little confusing (other than it replaces the "send"
     * from Dropzonejs) because really what it's doing is reading the file and
     * NOT sending to the server.
     */
    _sendIntercept(file, options={}) {
      return new RSVP.Promise((resolve,reject) => {
        if(!options.readType) {
          const mime = file.type;
          const textType = a(_textTypes).any(type => {
            const re = new RegExp(type);
            return re.test(mime);
          });
          options.readType = textType ? 'readAsText' : 'readAsDataURL';
        }
        let reader = new window.FileReader();
        reader.onload = () => {
          resolve(reader.result);
        };
        reader.onerror = () => {
          reject(reader.result);
        };
    
        // run the reader
        reader[options.readType](file);
      });
    },
    
      

    https://github.com/lifegadget/ui-dropzone/blob/0.7.2/addon/mixins/xhr-intercept.js#L10-L38

    上面的代码返回一个Promise,一旦被放入浏览器的文件已被"读取"进入Javascript。这应该是非常快的,因为它都是本地的(请注意,如果您正在下载非常大的文件,您可能想要" chunk"它......那就更多了高级主题)。

  • 挂钩 Dropzone

    现在我们需要在Dropzone中找到一个可以读取文件内容并停止我们不再需要的网络请求的地方。由于HTML5文件API只需要一个File对象,因此您会注意到Dropzone为此提供了各种挂钩。

    我决定接受&#34;接受&#34;钩子,因为它会让我有机会下载文件并一次性验证(对我而言,它主要是关于拖放XML,所以文件的内容是一部分< / em>验证过程)并且至关重要的是网络请求之前发生。

    现在重要的是你要意识到我们已经'#34;'&#34;更换&#34; accept函数不监听它发生的事件。如果我们只是听了,我们仍然会招致网络请求。所以**过载*接受我们做这样的事情:

    this.accept = this.localAcceptHandler; // replace "accept" on Dropzone
    

    仅当this Dropzone 对象时才会有效。你可以通过以下方式实现这一目标:

    • 将其包含在init挂钩功能
    • 将其作为实例化的一部分(例如new Dropzone({accept: {...}

    现在我们已经引用了#34; localAcceptHandler&#34;,让我向您介绍一下:

    localAcceptHandler(file, done) {
      this._sendIntercept(file).then(result => {
        file.contents = result;
        if(typeOf(this.localSuccess) === 'function') {
          this.localSuccess(file, done);
        } else {
          done(); // empty done signals success
        }
      }).catch(result => {
        if(typeOf(this.localFailure) === 'function') {
          file.contents = result;
          this.localFailure(file, done);
        } else {
          done(`Failed to download file ${file.name}`);
          console.warn(file);
        }
      });
    }
    
      

    https://github.com/lifegadget/ui-dropzone/blob/0.7.2/addon/mixins/xhr-intercept.js#L40-L64

    在快速摘要中,它执行以下操作:

    • 阅读文件的内容(又名_sendIntercept
    • 基于mime类型通过readAsTextreadAsDataURL
    • 读取文件
    • 将文件内容保存到文件的.contents属性
  • 停止发送

    要拦截在网络上发送请求但仍保留工作流程的其余部分,我们将替换名为submitRequest的函数。在Dropzone代码中,这个函数是一个单行,我所做的就是用我自己的单行代替它:

    this._finished(文件,&#39;本地解析,参考&#34;内容&#34;属性&#39;);

      

    https://github.com/lifegadget/ui-dropzone/blob/0.7.2/addon/mixins/xhr-intercept.js#L66-L70

  • 为检索到的文档提供访问

    最后一步是确保我们的localAcceptHandler代替 dropzone提供的accept例程:

      

    https://github.com/lifegadget/ui-dropzone/blob/0.7.2/addon/components/drop-zone.js#L88-L95

答案 2 :(得分:0)

使用FileReader()解决方案对我来说非常有用:

Dropzone.autoDiscover = false;
var dz = new Dropzone("#demo-upload",{
   autoProcessQueue:false,
   url:'upload.php'
});

dz.on("drop",function drop(e) {
              var files = [];
              for (var i = 0; i < e.dataTransfer.files.length; i++) {
                files[i] = e.dataTransfer.files[i];
              }


var reader = new FileReader();
reader.onload = function(event) {
    var line = event.target.result.split('\n');
    for ( var i = 0; i < line.length; i++){
        console.log(line);
    }
};
reader.readAsText(files[files.length-1]);