2012-08-25 66 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>

相關問題