【问题标题】:Checking HTML5 drag and drop file type检查 HTML5 拖放文件类型
【发布时间】:2011-11-11 09:09:47
【问题描述】:

我想将拖放区的背景颜色更改为绿色或红色,具体取决于包含的拖拽负载是否包含支持的文件类型 (JPEG)。

  • Gecko 和 Webkit 是否支持确定拖放文件的文件类型?

  • 如何在这两种浏览器中提取文件类型?

我找到了 event.dataTransfer.types API,但对于 Firefox,它似乎填充了 application/x-moz-file,因此我认为我做错了。

【问题讨论】:

  • 应该在 Gecko 中工作,WebKit 限制对数据传输对象的访问。你现在有什么代码?

标签: javascript html drag-and-drop


【解决方案1】:

您可以使用文件对象在 Gecko 和 webkit 支持的浏览器中获取文件类型。

var files =e.dataTransfer.files||e.target.files; // File list

文件对象返回名称、类型和大小。您也可以获取上次修改日期。

var mimeType= files[0].type; //mime type of file list first entry

【讨论】:

  • 为什么 || e.target.files 后备?有没有考虑到一些意外情况什么的?
  • 请注意,此 MIME 类型是使用文件扩展名(即文件名末尾的 .gif 或 .jpeg)生成的。这绝对不是文件的真正类型案例。许多人在保存 PNG 或 BMP 文件时会使用 .jpg... 因为他们知道 .jpg 的意思是“图像”。
  • @AlexisWilke,我认为你的情况是极端的极端情况。大多数人在保存文件时不会在 Windows 中键入扩展名(或隐藏)。但更重要的是,我怀疑大多数程序在扩展名不匹配时都有后备检测来从数据本身中找出文件类型。例如。在 png 文件的末尾添加 .jpg 并尝试在 photoshop(#1 照片编辑器)中打开它会导致 photoshop 抛出一个错误,即它是一个 invlaid jpg。如果您有扩展检测,并且用户将其更改为错误的,那么这是他们的问题,而不是您的问题。废话,废话。
  • 为什么文件类型会沿着该路径发生变化?每个操作系统都使用文件类型来确定文件是什么以及用什么适当的程序打开它,它不会解析开始数据来做出决定,它相信文件类型没有改变。在大多数情况下,它会警告用户不要更改文件类型,因为它可能会停止运行。为什么不保持简单并检查文件类型?
  • 我正在尝试使用最新版本的 Firefox 中的 dragenter 事件来做到这一点,但文件为空...
【解决方案2】:

在 JavaScript 中测试文件的类型需要做一些工作,但新版本的浏览器现在有 FileReader 对象允许您这样做。

这是对我的实现的不完整引用,它将缓冲区读取为 uint8 字节,然后检查输入是否为有效的 JPEG、GIF、PNG。显然,它会随着时间的推移而增强。如需更完整的版本,请查找editor.js file in the editor and the mimetype plugins of the snapwebsites project。

// The buffer is expected to be an ArrayBuffer() as read with a FileReader
_buffer2mime: function(buffer)
{
    buf = Uint8Array(buffer);
    if(buf[0] == 0xFF
    && buf[1] == 0xD8
    && buf[2] == 0xFF
    && buf[3] == 0xE0
    && buf[4] == 0x00
    && buf[5] == 0x10
    && buf[6] == 0x4A  // J
    && buf[7] == 0x46  // F
    && buf[8] == 0x49  // I
    && buf[9] == 0x46) // F
    {
        return "image/jpeg";
    }
    if(buf[0] == 0x89
    && buf[1] == 0x50  // P
    && buf[2] == 0x4E  // N
    && buf[3] == 0x47  // G
    && buf[4] == 0x0D  // \r
    && buf[5] == 0x0A) // \n
    {
        return "image/png";
    }
    if(buf[0] == 0x47  // G
    && buf[1] == 0x49  // I
    && buf[2] == 0x46  // F
    && buf[3] == 0x38  // 8
    && buf[4] == 0x39  // 9
    && buf[5] == 0x61) // a
    {
        return "image/gif";
    }

    // unknown
    return "";
},

_droppedImageAssign: function(e){
    var img,id;
    img = new Image();
    img.src = e.target.result;
    ++this._uniqueId;
    id="snap-editor-image-"+this._uniqueId;
    jQuery(img).hide().attr("id",id).appendTo(e.target.snapEditorElement);
    jQuery("#"+id).show();
},

_droppedImage: function(e){
    var mime, r, a, blob;

    mime = snapwebsites.EditorInstance._buffer2mime(e.target.result);
    if(mime.substr(0, 6) == "image/")
    {
        r = new FileReader;
        r.snapEditorElement = e.target.snapEditorElement;
        r.onload = snapwebsites.EditorInstance._droppedImageAssign;
        a = [];
        a.push(e.target.snapEditorFile);
        blob = new Blob(a, {type: mime}); // <- FORCE THE REAL MIME TYPE
        r.readAsDataURL(blob);
    }
},

jQuery("#some-object")
        .on("drop",function(e){
            // always prevent the default dropping mechanism
            // we handle the file manually all the way
            e.preventDefault();
            e.stopPropagation();

            // anything transferred on widget that accepts files?
            if(e.originalEvent.dataTransfer
            && e.originalEvent.dataTransfer.files.length)
            {
                accept_images = jQuery(this).hasClass("image");
                accept_files = jQuery(this).hasClass("attachment");
                if(accept_images || accept_files)
                {
                    for(i = 0; i < e.originalEvent.dataTransfer.files.length; ++i)
                    {
                        // read the image so we can make sure it is indeed an
                        // image and ignore any other type of files
                        r = new FileReader;
                        r.snapEditorElement = this;
                        r.snapEditorFile = e.originalEvent.dataTransfer.files[i];
                        r.onload = snapwebsites.EditorInstance._droppedImage;
                        // Get the first 64 bytes of the file to check the magic code
                        r.readAsArrayBuffer(r.snapEditorFile.slice(0, 64));
                    }
                }
            }

            return false;
        })

【讨论】:

    【解决方案3】:

    我认为您不能依靠浏览器来为您提供 MIME 类型。如果您检查文件扩展名,它会简单得多。 :)

    如果您真的想检查文件类型,请使用DataTransfer.getData() 读取有效负载并检查前导字节(PNG、GIF89、JFIF 或其他内容)。

    【讨论】:

    • 所以你真的认为文​​件扩展名是文件类型更可靠的指示???检查数据是唯一真正确定的方法。所谓的文件魔法。
    猜你喜欢
    • 2023-03-19
    • 2016-08-13
    • 2012-02-13
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2012-06-08
    • 1970-01-01
    相关资源
    最近更新 更多