2012-08-25 42 views
14

我有一个正常的<input type="file">文件上传的网站,在提交表单时将数据发布到后端。在没有AJAX的情况下拖放文件上传,在前台同步?

我想逐步增强表单,以便您可以从浏览器外部的任何位置(不仅仅在文件输入字段中,如内置于某些浏览器中)将文件从浏览器外部上传以便将其上传。

无论形式autosubmits并不重要。因此,如果拖放操作只选择文件字段中的文件,而不开始上传,那很好。我不需要支持多个文件。我不需要显示上传进度,缩略图或任何幻想。

我知道有一些支持拖放和拖放上传JS库,但他们似乎都通过AJAX上传。我可以做到这一点,但后来我需要修改后端和前端来处理上传错误,重定向并在成功上显示正确的消息等等。

我希望有一个渐进增强,不需要任何后端更改。它应该使用页面中的表单同步发生。 JS很好,只要上传发生在“前台”。当然,同步AJAX不起作用。

+1

在Chrome中,至少,你可以设置在降的文件输入的文件:http://jsfiddle.net/qMmPr/。那是你的追求? – pimvdb

+0

@ pimvdb这很美!正是我想要的。我忘了提及,因为这是一个内部服务,所以Chrome只有很好。如果您将其写为回答(除了评论),我会将其标记为已接受。 –

回答

15

虽然不是真的“同步”(JavaScript执行不会实际停止),但可以通过编程方式设置<input type="file">所选的文件。事实上,这些元素和拖动共享其文件后端实现(FileFileList实例),所以它非常简单。更重要的是,由于前两个使用FileList s,拖动多个文件的工作就像无缝一样。

此作品在Chrome(使用jQuery):http://jsfiddle.net/qMmPr/

$(document).on("dragover drop", function(e) { 
    e.preventDefault(); // allow dropping and don't navigate to file on drop 
}).on("drop", function(e) { 
    $("input[type='file']") 
     .prop("files", e.originalEvent.dataTransfer.files) // put files into element 
     .closest("form") 
      .submit(); // autosubmit as well 
}); 
+0

@Henrik N:我现在意识到它不喜欢Windows上的'.lnk'文件。通过输入元素选择它们会选择快捷方式链接的文件,而删除'.lnk'文件则会得到'.lnk'文件本身。 – pimvdb

+0

对我的用例不是问题。再次感谢! –

+3

跨浏览器解决方案的任何想法? (刚刚在FF16上测试了prop():不工作) –

-1

它可以通过转动autoUpload为假,收集在一个阵列中的文件来进行,然后在表单提交做与所有与表单数据一起文件的单个AJAX调用,如所描述here

+0

感谢这一点,但注意“没有Ajax”在问题:) –

+0

的确,我的方法仍然使用ajax,但它只是一个请求,并以这种方式显示为用户的正常提交操作。 – Tor

+0

是的,在很多情况下它绝对是一个很好的解决方案。但正如问题所提到的,通过Ajax实现意味着您需要特殊的错误处理等等。这不是我在这种情况下,但我赞赏输入都是一样的:) –

0

感谢@pimvdb评论,我想出了一个非常优雅的解决方案。

由于在<input type="file" />上的拖放工作,为什么不在dragstart上全屏显示以确保用户不会错过它?无论如何,他正拖着脚走,所以他的意图在这个时候是清楚的。

这里有一个演示:https://jsfiddle.net/08wbo4um

注:不幸的是这似乎并没有在iframe工作,但它的实际网页上的工作。你仍然可以理解这种行为。

这里的片段:

$('input[type="file"]').on('change', function(e){ 
 
    var fileName = e.target.files[0].name; 
 
    if (fileName) { 
 
     $(e.target).parent().attr('data-message', fileName); 
 
    } 
 
    }); 
 
    
 
    $(document).on('drag dragstart dragend dragover dragenter dragleave drop', function(e) { 
 
    if ($('input[type="file"]').length) { 
 
     if (['dragover', 'dragenter'].indexOf(e.type) > -1) { 
 
     if (window.dragTimeout) 
 
      clearTimeout(window.dragTimeout); 
 
     $('body').addClass('dragged'); 
 
     } else if (['dragleave', 'drop'].indexOf(e.type) > -1) { 
 
     // Without the timeout, some dragleave events are triggered 
 
     // when the :after appears, making it blink... 
 
     window.dragTimeout = setTimeout(function() { 
 
      $('body').removeClass('dragged'); 
 
     }, 100); 
 
     } 
 
    } 
 
    });
h3, p { 
 
    text-align: center; 
 
} 
 

 
.form-group { 
 
    margin: 30px; 
 
} 
 

 
.file-upload .form-control { 
 
    height: 150px; 
 
    outline: 1px dashed #ccc; 
 
    outline-offset: -15px; 
 
    background-color: #eee; 
 
} 
 
.file-upload .form-control:before { 
 
    content: "\f093"; 
 
    font: normal normal normal 14px/1 FontAwesome; 
 
    font-size: 3em; 
 
    left: 0; 
 
    right: 0; 
 
    display: block; 
 
    margin: 20px auto; 
 
    text-align: center; 
 
} 
 
.file-upload .form-control:after { 
 
    content: attr(data-message); 
 
    left: 0; 
 
    right: 0; 
 
    bottom: 0; 
 
    text-align: center; 
 
    display: block; 
 
} 
 
.file-upload .form-control input[type="file"] { 
 
    cursor: pointer; 
 
    opacity: 0; 
 
    width: 100%; 
 
    height: 100%; 
 
    position: absolute; 
 
    top: 0; 
 
    bottom: 0; 
 
    right: 0; 
 
    left: 0; 
 
} 
 
body.dragged .file-upload .form-control input[type="file"] { 
 
    /* Make sure it is full screen, whatever the position absolute container */ 
 
    position: fixed; 
 
    top: -50vh; 
 
    bottom: -50vh; 
 
    left: -50vw; 
 
    right: -50vw; 
 
    height: 200vh; 
 
    width: 200vw; 
 
    z-index: 10002; 
 
} 
 

 
body:after { 
 
    content: 'You can drop the file. :-)'; 
 
    font-size: 2em; 
 
    text-align: center; 
 
    line-height: 100vh; 
 
    position: absolute; 
 
    top: 10px; 
 
    bottom: 10px; 
 
    left: 10px; 
 
    right: 10px; 
 
    background-color: #eee; 
 
    z-index: 10000; 
 
    border-radius: 4px; 
 
    border: thin solid #ccc; 
 
    visibility: hidden; 
 
    opacity: 0; 
 
    transition: visibility 0s, opacity 0.5s ease; 
 
} 
 

 
body.dragged:after { 
 
    opacity: 1; 
 
    visibility: visible; 
 
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/> 
 
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> 
 

 
<h3>Drag N Drop file upload without AJAX Demo</h3> 
 
<p>Try drag and dropping a file. :-)</p> 
 

 
<div class="form-group file-upload" required="required"> 
 
    <label class="cols-sm-2 control-label" for="document_file">File Upload</label><br> 
 
    <div class="cols-sm-10"> 
 
     <div class="input-group"> 
 
     <span class="input-group-addon"><i class="fa fa-file" aria-hidden="true"></i></span> 
 
     <div class="form-control" data-message="Click to select file or drag n drop it here"> 
 
      <input required="required" title="Click to select file or drag n drop it here" type="file" name="document[file]" id="document_file"> 
 
     </div> 
 
     </div> 
 
    </div> 
 
    </div>

相关问题