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 + '
' + 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();
}
})();
php
$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



沒有留言:
張貼留言