2010-04-17 73 views
68

拖放文件上传可以在Firefox 3.6中完成。在Google Chrome/Chromium和Safari中拖放文件上传?

A Google search for html5 drag-and-drop file uploading -gmail给出了诸如:

所有这些指南的使用FileReader(或火狐3.6的过时getAsBinary,这是任何其他浏览器支持,或者)。

但是,Google最近发布了Gmail的更新,允许在Chromium和Firefox上拖放文件上传,以及Chromium does not have FileReader。我每晚都使用最新的Chromium,它可以拖放上传文件,但不支持FileReader

我见过有人提到可以通过拖拽到<input type="file" />上拖放上传,但一次只能支持一个文件,而Gmail的上传者可以处理多个文件被拖拽到上面,所以很明显不是他们在做什么。

所以问题是,他们是如何做到的?您如何支持Chromium for HTML5文件上传?另外,你能否支持Safari?

+2

附:阅读源代码非常困难,因为Gmail的源代码由于其所做的所有优化而相当混乱。 – Zarel 2010-04-17 07:47:14

+1

P.P.S. HTML''的'FileList'是只读的,所以你不能将一个拖放文件移植到其中一个文件中。 – Zarel 2010-04-17 20:51:00

+0

是否可以更改此帖子的标题?我刚刚在“Chrome”中发布了一个关于“拖放”的重复问题,但它与此问题不匹配,因为标题使用Chromium(大多数人不使用)。 – 2010-05-25 15:12:19

回答

33

警告:这是适用于非常旧版本Safari和Chrome的兼容性代码。现代浏览器都支持FileReader API;这里有一个教程:https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

此代码现在仅在某些原因需要支持Safari 5或更旧版本或者Chrome 6及更旧版本时才有用。


一种可能性是使用the method used in SwellJS

使用<input type="file" multiple="multiple" />像这样:

<form method="post" enctype="multipart/form-data" id="uploadform"> 
    <input type="file" name="dragupload[]" multiple="multiple" 
    onchange="if (this.value) document.getElementById('uploadform').submit();" /> 
</form> 

输入元件可以在接受上载的一个元件被造型为具有opacity: 0并定位(绝对) 。整个表单可以放置在iframe之内用于“伪阿贾克斯”状行为。上传元素可以是一个隐藏的层,直到有东西被拖动。

这样一个iframe会是什么样子:

<script> 
<!-- 
    var entered = 0; 
--> 
</script> 
<body ondragenter="entered++;document.getElementById('uploadelement').style.display='block'" ondragleave="entered--;if (!entered) document.getElementById('uploadelement').style.display='none'"> 
    <form method="post" enctype="multipart/form-data" id="uploadform"> 
    Things can be dragged and dropped here! 
    <input type="file" id="uploadelement" name="dragupload[]" multiple="multiple" onchange="if (this.value) { document.getElementById('uploadform').submit(); }" style="display:none;position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;" /> 
    </form> 
</body> 

检测的Safari或Chrome时,这只能做(因为其他的浏览器不支持拖放和拖放到<input type="file" />元素),并可以与Firefox 3.6+的HTML5 drop事件组合使用。

我不能说这是否是Gmail使用的方法,但它当然也适用。

+0

显示/隐藏代码的入口计数增加/减少技巧非常方便。 – 2011-12-14 18:07:53

+0

感谢您发布此信息。你有可能从这里链接到一个完整的例子吗?一个可能包含服务器端代码? 或只是解释(在asp.net上)如何访问从此表单提交的文件(“uploadForm”) – Guy 2011-12-27 08:58:38

10

我有很多很多很多侦探工作后在Chrome中工作。此只有适用于Chrome。在Safari上,它冻结。在Firefox上,它不会让我删除文件。IE打开掉落的文件。即使在Chrome中,由于某种原因,拖放只能使用一次,之后您必须刷新页面。 (一个可能的原因是,什么是错与事件处理程序。)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <script type="text/javascript"> 
      window.onload = function() { 
       var div = document.getElementById('div'); 
       div.ondragenter = div.ondragover = function (e) { 
        e.preventDefault(); 
        e.dataTransfer.dropEffect = 'copy'; 
        return false; 
       } 
       div.ondrop = function (e) { 
        for (var i = 0; i < e.dataTransfer.files.length; i++) { // e.dataTransfer is a DataTransfer object (https://developer.mozilla.org/En/DragDrop/DataTransfer), e.dataTransfer.files is a FileList object (https://developer.mozilla.org/en/DOM/FileList) 
         var file = e.dataTransfer.files[i]; // file is a File object (https://developer.mozilla.org/en/DOM/File) 

         var xhr = new XMLHttpRequest; 
         xhr.open('post', 'handler.php', true); 
         xhr.onreadystatechange = function() { 
          if (this.readyState != 4) 
           return; 
          document.body.innerHTML += '<pre>' + this.responseText + '</pre>'; 
         } 
         xhr.setRequestHeader('Content-Type', 'multipart/form-data'); 
         xhr.setRequestHeader('X-File-Name', file.fileName); 
         xhr.setRequestHeader('X-File-Size', file.fileSize); 
         xhr.send(file); // For some reason sending the actual File object in Chrome works? 
        } 

        e.preventDefault(); 
        return false; 
       } 
      } 
     </script> 
    </head> 
    <body> 
     <div id="div" style="width: 100%; height: 200px; border: 1px solid blue">Drop here</div> 
    </body> 
</html> 

handler.php:

// This is not a true file upload. Instead, it sends the raw data directly. 
    echo htmlentities(file_get_contents('php://input')); 
+3

使用document.body.innerHTML + =销毁dom事件。避免这会解决你的问题。 – Gorilla3D 2010-12-13 20:58:42

+0

很好,我告诉gmail dev你应该使用dropEffect ='移动'为FF3.6 +,还没有测试过FF,所以不知道这是否仍然需要 – gatapia 2011-03-14 20:17:02

2

你不会需要使用iframe做伪AJAX上传。 Chrome和Safari都支持XHR2 uploads进度事件,因此您可以进度条等。

+0

...是的,这很明显。这里的问题是我看到的所有教程都使用FileReader或getAsBinary()函数(即Chrome不支持的函数)来上传文件。我怀疑这是需要的,所以我基本上在这里做的是询问如果有人想要Chrome的支持,会如何去做。 – Zarel 2010-04-22 10:56:04

+1

我最近编写了另一个教程,介绍Google如何在Gmail中进行拖放上传 - http://cssn.in/ja/027 使用xhr2上传并不需要getAsBinary当您处理文件时输入,这是Gmail为Chrome所做的工作 本文是一篇很好的阅读,如何使用xhr2上传来异步上传文件中的多个文件输入http://webreflection.blogspot.com/2009/03/safari-4- multiple-upload-with-progress.html – 2010-04-22 13:31:28

13

您可能感兴趣的是更符合技术和浏览器的内容。

在我看来,Plupload是否良好,支持以下功能:

  • 分块
  • 拖/放
  • PNG调整大小
  • JPEG调整大小
  • 类型过滤
  • 流式上传
  • 多部分上传
  • 文件大小限制
  • 上传进度

大多数以下技术:

  • 闪存
  • 齿轮
  • HTML 5
  • Silverli GHT
  • 的BrowserPlus

是的,since 2010.05.27,它支持在Chrome测试版运行HTML5拖/放。

+0

我刚刚在Chrome 6 for Mac上测试它:它不起作用。 – Zarel 2010-06-02 07:23:48

+0

哦?您是否尝试过此页面的“HTML 5运行时”? http://www.plupload.com/example_all_runtimes.php – 2010-06-02 07:53:09

+0

是的,我专门尝试了HTML 5运行时。 – Zarel 2010-07-27 09:08:24

2

对于我们自己的应用程序,我们只对FireFox进行拖放操作。我们恢复到其他人的传统iframe上传。为了检测是否支持拖放操作,我们运行以下代码:

if (typeof(window.File) == 'object' && typeof(window.FileReader) == 'function' && typeof(window.FileList) == 'object') { 
    // DnD is supported! 
} 

希望这对一些人有所帮助。

+0

谢谢 - 它是有帮助的:) – 2010-09-15 23:33:44

+0

你确实提到你只是为了FireFox而拖放,但对于其他可能使用此代码的人,Safari 5(Windows)将为'window.FileReader'检查返回false,即使它可以很好地处理文件丢弃。仍在寻找可靠的浏览器功能检测文件拖放功能... – Chris 2013-04-09 14:43:53

0

你可以使用FormData存储文件,然后上传它。 e.g

function setUp(){ 
    var dropContainer = document.getElementById("container"); 
    dropContainer.addEventListener("drop",dropHandler,false); 
    dropContainer.addEventListener("dragenter", function(event){event.stopPropagation();event.preventDefault();}, false); 
    dropContainer.addEventListener("dragover", function(event){event.stopPropagation();event.preventDefault();}, false); 
    dropContainer.addEventListener("drop", dropHandler, false); 
    getResult() 
} 
function dropHandler(event){ 
    var files = event.dataTransfer.files; 
    var count = files.length; 
    form = new FormData(); 
    for(var i= 0;i<count;i++){ 
    form.append("file"+i, files[i]); 
    } 
    sendData(); 
} 
function sendData(){ 
    var xhr = new XMLHttpRequest(); 
    xhr.upload.addEventListener("progress", uploadProgress, false); 
    xhr.addEventListener("load", uploadComplete, false); 
    xhr.addEventListener("error", uploadFailed, false); 
    xhr.open("POST", "/upload"); 
    xhr.send(form); 
    var progressBar = document.getElementById('progressBar'); 
    progressBar.style.display = 'block'; 
    progressBar.style.width = '0px'; 
} 

演示是在这里(http://flexinnerp.appspot.com/) 很享受这样的:)

1

最新的浏览器支持文件上传好。 你可以使用:

xhr = new XMLHttpRequest();  
xhr.open('POST', targetPHP, true); 
var formData = new FormData(); 
formData.append('upload',file); 
xhr.send(formData); 

你并不需要设置边界或任何头,就这样它工作正常。火狐6.02和在铬13 服务器:用 “弹簧MVC”

0

设定多个属性如Tomcat:

INPUT TYPE = “文件” 名称= “file1的” 多 我在 客户端测试此代码= “多” 级= “DropHere”

和使用CSS DropHere类:

.DropHere 
{ 
    height: 100px; 
    padding: 3px; 
    border: 2px dashed #555; 
    border-radius: 5px; 
    cursor: default; 
    background-image:url("data:image/svg+xml;utf8, <svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='100px' width='220px'><text x='55' y='75' font-size='20'>or drop files here</text></svg>"); 
    background-repeat: no-repeat; 
} 

文件字段现在看起来像:

The file will now look like

如果使用asp.net你可能还喜欢这篇文章,我写“有进度条和拖放多文件上传”:http://www.codeproject.com/Articles/818561/Multiple-file-upload-with-progress-bar-and-drag-an