chrome
firefox
safari
> ie9 或許吧
html
HTML5 File Drag & Drop Upload HTML5 File Drag & Drop Upload
Status Messages
legend { font-weight: bold; color: #333; } #filedrag { font-weight: bold; text-align: center; padding: 1em 0; margin: 1em 0; color: #555; border: 2px dashed #555; border-radius: 7px; cursor: default; } #filedrag.hover { color: #f00; border-color: #f00; border-style: solid; box-shadow: inset 0 3px 4px #888; } #messages { padding: 0 10px; margin: 1em 0; border: 1px solid #999; } #progress p { display: block; width: 240px; padding: 2px 5px; margin: 2px 0; border: 1px inset #446; border-radius: 5px; background: #eee url("progress.png") 100% 0 repeat-y; } #progress p.success { background: #0c0 none 0 0 no-repeat; } #progress p.failed { background: #c00 none 0 0 no-repeat; } #total_progress { background-color: rgba(78,122,234,0.87); width: 0%; }js
(function() { // 用來計算全部上傳的 progress bar var totalSize = 0, totalLoad = 0; var total_progress = $id("total_progress"); // getElementById function $id(id) { return document.getElementById(id); } // output information function Output(msg) { var m = $id("messages"); m.innerHTML = msg + 'php
' + m.innerHTML; } // file drag hover function FileDragHover(e) { e.stopPropagation(); e.preventDefault(); e.target.className = (e.type == "dragover" ? "hover" : ""); } // file selection function FileSelectHandler(e) { // cancel event and hover styling FileDragHover(e); // fetch FileList object var files = e.target.files || e.dataTransfer.files; // process all File objects for (var i = 0, f; f = files[i]; i++) { totalSize+= f.size; // 用 post 的方式 upload var form = new FormData(); form.append('fileselect', f); UploadFile(f, form); } } // upload JPEG files function UploadFile(file, form) { // following line is not necessary: prevents running on SitePoint servers if (location.host.indexOf("sitepointstatic") >= 0) return var xhr = new XMLHttpRequest(); if (xhr.upload && file.size <= $id("MAX_FILE_SIZE").value) { // create progress bar var o = $id("progress"); var progress = o.appendChild(document.createElement("p")); progress.appendChild(document.createTextNode("upload " + file.name)); // 計算總上傳進度用 var prev = 0, // 前一次 e.loaded 的檔案 size x = 0; // 每一回 e.loaded 的值 (加總後便等於原 size) // progress bar xhr.upload.addEventListener("progress", function(e) { // 畫出每筆上傳的 progress bar var pc = parseInt(100 - (e.loaded / e.total * 100)); progress.style.backgroundPosition = pc + "% 0"; if (prev == 0) { x = e.loaded; // 紀錄第一筆 e.loaded 的值 prev = e.loaded; // 這次的 e.loaded 做為下一回的 prev } else { x = e.loaded - prev; // 第一筆後, 紀錄 e.loaded 與上一次的差值 prev = e.loaded; // 這次的 e.loaded 做為下一回的 prev } totalLoad+= x; // 畫出總上傳的 progress bar var percent = parseInt((totalLoad / totalSize * 100)); total_progress.style.width = percent + '%'; }, false); // file received/failed xhr.onreadystatechange = function(e) { if (xhr.readyState == 4) { Output(file.name+' upload done.'); progress.className = (xhr.status == 200 ? "success" : "failure"); return true; } }; // start upload //xhr.setRequestHeader("X_FILENAME", file.name); // 用 X_FILENAME 的方式會佔用記憶體, 不適用影片上傳 xhr.open("POST", $id("upload").action, true); xhr.send(form); } } // initialize function Init() { var fileselect = $id("fileselect"), filedrag = $id("filedrag"), submitbutton = $id("submitbutton"); // file select fileselect.addEventListener("change", FileSelectHandler, false); // is XHR2 available? var xhr = new XMLHttpRequest(); if (xhr.upload) { // file drop filedrag.addEventListener("dragover", FileDragHover, false); filedrag.addEventListener("dragleave", FileDragHover, false); filedrag.addEventListener("drop", FileSelectHandler, false); filedrag.style.display = "block"; } } // call initialization file if (window.File && window.FileList && window.FileReader) { Init(); } })();
$fn = (isset($_SERVER['HTTP_X_FILENAME']) ? $_SERVER['HTTP_X_FILENAME'] : false); if ($fn) { # 以 xhr.setRequestHeader("X_FILENAME", file.name) 方式上傳; 會佔記憶體 // AJAX call file_put_contents( 'uploads/' . $fn, file_get_contents('php://input') ); echo "$fn uploaded"; exit(); } else { # 以 post 方式上傳 $file = $_FILES['fileselect']; //error_log('$file : '.json_encode($file)); //error_log($file['name'].' / '.$file['tmp_name'].' / '.$file['size'].' / '.$file['type']); if (move_uploaded_file($file['tmp_name'], 'uploads/' . $file['name'])) { error_log('upload success. '.$file['name']); } else { error_log('upload failed. '.$file['name']); } }
前年在試寫這個功能時, 用 firefox 做上傳的 post 時, 還要自己兜 post 字串, 有夠麻煩
(見 http://blog.xuite.net/choubee/blog/41250553 )
而現在 firefox 現在也可像 chrome 一樣直接把 form 以 post 方式 send 出去
這真是一個好消息啊~
然後這次參考的範例原本是用 xhr.setRequestHeader("X_FILENAME", file.name) 的方式上傳,
然後 php 再用 file_put_contents() 的方式去接
但這樣做看起來是把 upload file 存到 ram 裡, 上傳的檔是影片, 這樣 server 會吃不消
所以還是使用了 post 的方式來做, 就紀錄一下這個新的方式~
執行畫面
cf : http://blogs.sitepointstatic.com/examples/tech/filedrag/1/index.html
沒有留言:
張貼留言