我应该为 HTML5 拖放操作使用啥格式(MIME 类型)?

Posted

技术标签:

【中文标题】我应该为 HTML5 拖放操作使用啥格式(MIME 类型)?【英文标题】:What format (MIME Type) should I use for HTML5 drag and drop operations?我应该为 HTML5 拖放操作使用什么格式(MIME 类型)? 【发布时间】:2011-10-09 16:12:41 【问题描述】:

我开始尝试使用 html5 拖放。然后,在 dragstart 事件处理程序中我们应该运行setData(),它接收两个参数:formatdata

function dragstart_handler(ev) 
    ev.dataTransfer.setData('text/plain', 'foobar');

我想将某种“对象”从一个容器拖到另一个容器中,在我的 Web 应用程序中。我所说的“对象”是指具有多个属性(颜色、文本、作者、日期……)的东西。

我应该使用哪种格式(或 MIME 类型)?

text/plain? text/x-myapp-myobjtype? application/x-myapp-myobjtype? application/x-myapp.myobjtype+json? 还有别的吗? 不止一个?

我应该如何编码我的对象(setData()data 参数)?

逗号分隔(或任何其他分隔符)键=值对? 使用 JSON 序列化对象? 只是一个 id,在 dropzone 中我必须只使用 id 检索完整的对象吗? 只发送对对象的引用,甚至不序列化任何东西? (不可能,data 参数必须是字符串)

(我意识到“如何对拖放对象进行编码”在这里可能是另一个问题,但它与 MIME 类型的选择密切相关)


一些参考资料:

http://dev.w3.org/html5/spec/dnd.html http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dnd https://developer.mozilla.org/En/DragDrop/Drag_Operations https://developer.mozilla.org/En/DragDrop/DataTransfer http://www.html5rocks.com/en/tutorials/dnd/basics/

【问题讨论】:

这真的取决于你在做什么,但是'application/json'和一个 JSON 序列化对象似乎是不错的选择...... 但是application/json 是不是太笼统了?按照这个建议,任何 OpenOffice 文档也应该有 application/zip MIME 类型,因为它们实际上是压缩文件。 进一步改进我的观点:如果我使用application/json,那么,以此类推,所有的SVG图像都应该是application/xml而不是image/svg+xml,因为它们也是XML文档。相同的逻辑适用于使用 XML 序列化的任何内容(例如当前使用 application/vnd.google-earth.kml+xml 类型的 Google 地球 KML 文件;或使用 application/atom+xml 的 Atom 提要)。 【参考方案1】:

HTML5 规范有一些拖放示例(参见current working draft 或latest version)。在此类示例中,使用了自定义 MIME 类型,并且还建议使用特定于站点的 MIME 类型。看到这个sn-p:

<p>Drop your favorite fruits below:</p>
<ol dropzone="move s:text/x-example" ondrop="dropHandler(event)">
 <-- don't forget to change the "text/x-example" type to something
 specific to your site -->
</ol>
<script>
  var internalDNDType = 'text/x-example'; // set this to something specific to your site
[...]

那么,太好了,这意味着我们应该使用自定义 MIME 类型! (除非我们实际上是在拖动纯文本,或者只是一个 URL,或者已经具有众所周知的类型)

但是我们如何创建这样的自定义 MIME 类型呢?

我没有找到关于这个的文档,所以我查看了其他 MIME 类型。 list of text media types 没有什么特别之处,但 list of application media types 很有趣。让我从该列表中获取一个示例:

application/atom+xml
application/xhtml+xml
application/xmpp+xml

application/vnd.google-earth.kml+xml
application/vnd.google-earth.kmz
application/vnd.iptc.g2.newsitem+xml
application/vnd.iptc.g2.packageitem+xml
application/vnd.nokia.iptv.config+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
application/vnd.yamaha.openscoreformat.osfpvg+xml

application/vnd.hal+json
application/vnd.hal+xml

我可以注意到命名的模式:

一个点分层分隔多个“元素”(例如,configiptv 的子级,即nokia 的子级,即vnd 的子级)。 连字符分隔复合词(如google-earthopenxmlformats-officedocument)。 加号用于进一步指定序列化格式(在这些示例中为+json+xml)。 x- 前缀应用于未向 IANA 注册的 MIME 类型(因此,未显示在该列表中)。

基于这些规则,我可以建议使用以下 MIME 类型:

application/x-mysite.myobject+json(或application/x-mysite.parentobject.childobject+json

这似乎是为以 JSON 编码的 Web 应用程序对象指定自定义 MIME 类型的最精确和正确的方法。

【讨论】:

不应该把“x-”前缀换成“vnd.”吗? x- 前缀用于未向 IANA 注册的 MIME 类型。但是,vnd. 前缀用于已向 IANA 注册的特定于供应商的 MIME 类型。 (顺便说一句,好问题!)【参考方案2】:

更新:此 Chrome 错误已从版本 19 开始修复。

如果我打算支持Google Chrome(现在是最新版本12),那么我必须坚持text/plain

那是因为Chrome has improperly implemented the dataTransfer object,并且有一个关于dataTransfer not working with non text or url 的开放错误。

我写了一个simple desmontration at jsFiddle。它在Mozilla Firefox 3.6 甚至Arora browser(0.10.2 版,WebKit 533.3 版)中都能正常工作。为了完整起见,我的 Chrome 版本是 12.0.742.112(WebKit 版本 534.30)。下面还有演示代码:

<div id="drag" draggable="true">Drag me!</div>
<div id="drop">Drop here!</div>


#drag, #drop 
    padding: 1em 2em;
    margin: 1em 0;

#drag 
    background: #CFC;

#drop 
    background: #FCC;



function dragstart_handler(ev) 
    console.log('dragstart');
    ev.dataTransfer.setData('text/x-example', 'Foobar');


function dragover_handler(ev) 
    // Accepting whatever is dragged over here
    ev.preventDefault();


function drop_handler(ev) 
    console.log('drop');
    console.log(ev.dataTransfer.types);

    if (ev.dataTransfer.types) 
        var i;
        for (i = 0; i < ev.dataTransfer.types.length; i++) 
            var type = ev.dataTransfer.types[i];
            console.log(type, ev.dataTransfer.getData(type));
        
    

    console.log(ev.dataTransfer.getData('text/x-example'));


var drag = document.getElementById('drag');
drag.addEventListener('dragstart', dragstart_handler, false);

var drop = document.getElementById('drop');
drop.addEventListener('dragover', dragover_handler, false);
drop.addEventListener('drop', drop_handler, false);

【讨论】:

Chrome 错误已从 19 版开始修复。 又被第22版破解(可能更早) @rtcarlson 在 Linux 上运行 Google Chrome 29.0.1547.62。我的答案中链接的演示在这里可以正常工作,所以我认为这个错误现在不存在了。 (顺便说一句,Chrome 22 已经很老了……) 在 IE11 中好像坏了 =(【参考方案3】:

使用 'application/json' 作为您可能喜欢的任何其他元数据的包装器,包括链接文件的 mime 类型或您想在浏览器中使用的 html。

 'assets': [
      
       'color': 'foo',
       'text': 'bar',
       'uri': 'http://', // location of asset
       'type': 'application/zip', // mime-type of asset
       'html': '<div>html representation</div>'
       // .. more properties
      
   // ...more assets
   ]

【讨论】:

Plain application/json 感觉不对。也许类似于application/x-myapp.myobj+json

以上是关于我应该为 HTML5 拖放操作使用啥格式(MIME 类型)?的主要内容,如果未能解决你的问题,请参考以下文章

跨浏览器 HTML5 拖放 JSON 数据传输失败

电子邮件标题:MIME 版本:1.0 - 啥时候应该使用它?

使用 javascript 进行 HTML5 拖放 DOM 操作

各种剪贴板/拖放格式是啥意思?

我应该为一个简单的 HTML5 + jQuery 应用程序使用啥 JavaScript UI 测试框架?

HTML5 拖放无法正常工作