Наша новая статья расскажет вам о загрузке файлов HTML5. Да, я объяснял основы загрузки файлов html5 в прошлом (в одной из наших предыдущих статей), но сегодня я хотел бы привести вам другой пример, более лучший. Теперь вы можете просто перетащить изображения (несколько изображений), чтобы начать загрузку. Кроме того, скрипт отображает общий прогресс (в процентах, плюс оставленные файлы) и ответ сервера (без фактической загрузки). Я собираюсь отобразить прогресс в элементе Canvas в реальном времени. И наконец — наш скрипт может загружать файлы не только на свой сервер, но и на другой (можно сказать, что это межсайтовый загрузчик).
Вот наши демонстрационные и загружаемые пакеты:
Live Demo
скачать в упаковке
Хорошо, скачайте исходники и начнем!
Шаг 1. HTML
Первый — HTML-разметка:
index.html
<div class="container"> <div class="contr"><h2>Drag and Drop your images to 'Drop Area' (up to 5 files at a time, size - under 256kb)</h2></div> <div class="upload_form_cont"> <div id="dropArea">Drop Area</div> <div class="info"> <div>Files left: <span id="count">0</span></div> <div>Destination url: <input id="url" value="http://www.script-tutorials.com/demos/257/upload.php"/></div> <h2>Result:</h2> <div id="result"></div> <canvas width="500" height="20"></canvas> </div> </div> </div> <script src="js/script.js"></script>
Как видите, он состоит из нескольких основных элементов: «Область перетаскивания» слева и «Информационный блок» справа. Когда мы перетаскиваем файлы изображений на нашу dropArea, в блоке Info мы получаем ответ от сервера. Обратите внимание на элемент «URL назначения». Прямо сейчас это связано с нашим сервером. Но вы можете изменить его на свой URL в любое время.
Шаг 2. CSS
CSS / main.css
Теперь пришло время настроить наш макет:
CSS / main.css
.container { overflow:hidden; width:960px; margin:20px auto; } .contr { background-color: #212121; color: #FFFFFF; padding: 10px 0; text-align: center; border-radius:10px 10px 0 0; -moz-border-radius:10px 10px 0 0; -webkit-border-radius:10px 10px 0 0; } .upload_form_cont { background: -moz-linear-gradient(#ffffff, #f2f2f2); background: -ms-linear-gradient(#ffffff, #f2f2f2); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f2f2f2)); background: -webkit-linear-gradient(#ffffff, #f2f2f2); background: -o-linear-gradient(#ffffff, #f2f2f2); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f2f2f2'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f2f2f2')"; background: linear-gradient(#ffffff, #f2f2f2); color: #000; overflow: hidden; } .info { background-color: #EEEEEE; border: 1px solid #DDDDDD; float: left; font-weight: bold; height: 530px; margin: 20px; position: relative; width: 560px; } .info > div { font-size: 14px; font-weight: bold; padding: 10px 15px 5px; } .info > h2 { padding: 0 15px; } .info > canvas { margin-left: 15px; margin-bottom: 10px; } .info #url { width: 400px; } #dropArea { background-color: #DDDDDD; border: 3px dashed #000000; float: left; font-size: 48px; font-weight: bold; height: 530px; line-height: 530px; margin: 20px; position: relative; text-align: center; width: 300px; } #dropArea.hover { background-color: #CCCCCC; } #dropArea.uploading { background: #EEEEEE url(loading.gif) center 30% no-repeat; } #result .s, #result .f { font-size: 12px; margin-bottom: 10px; padding: 10px; border-radius:10px; -moz-border-radius:10px; -webkit-border-radius:10px; } #result .s { background-color: #77fc9f; } #result .f { background-color: #fcc577; }
Шаг 3. HTML5 JS
JS / script.js
// variables var dropArea = document.getElementById('dropArea'); var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); var count = document.getElementById('count'); var destinationUrl = document.getElementById('url'); var result = document.getElementById('result'); var list = []; var totalSize = 0; var totalProgress = 0; // main initialization (function(){ // init handlers function initHandlers() { dropArea.addEventListener('drop', handleDrop, false); dropArea.addEventListener('dragover', handleDragOver, false); } // draw progress function drawProgress(progress) { context.clearRect(0, 0, canvas.width, canvas.height); // clear context context.beginPath(); context.strokeStyle = '#4B9500'; context.fillStyle = '#4B9500'; context.fillRect(0, 0, progress * 500, 20); context.closePath(); // draw progress (as text) context.font = '16px Verdana'; context.fillStyle = '#000'; context.fillText('Progress: ' + Math.floor(progress*100) + '%', 50, 15); } // drag over function handleDragOver(event) { event.stopPropagation(); event.preventDefault(); dropArea.className = 'hover'; } // drag drop function handleDrop(event) { event.stopPropagation(); event.preventDefault(); processFiles(event.dataTransfer.files); } // process bunch of files function processFiles(filelist) { if (!filelist || !filelist.length || list.length) return; totalSize = 0; totalProgress = 0; result.textContent = ''; for (var i = 0; i < filelist.length && i < 5; i++) { list.push(filelist[i]); totalSize += filelist[i].size; } uploadNext(); } // on complete - start next file function handleComplete(size) { totalProgress += size; drawProgress(totalProgress / totalSize); uploadNext(); } // update progress function handleProgress(event) { var progress = totalProgress + event.loaded; drawProgress(progress / totalSize); } // upload file function uploadFile(file, status) { // prepare XMLHttpRequest var xhr = new XMLHttpRequest(); xhr.open('POST', destinationUrl.value); xhr.onload = function() { result.innerHTML += this.responseText; handleComplete(file.size); }; xhr.onerror = function() { result.textContent = this.responseText; handleComplete(file.size); }; xhr.upload.onprogress = function(event) { handleProgress(event); } xhr.upload.onloadstart = function(event) { } // prepare FormData var formData = new FormData(); formData.append('myfile', file); xhr.send(formData); } // upload next file function uploadNext() { if (list.length) { count.textContent = list.length - 1; dropArea.className = 'uploading'; var nextFile = list.shift(); if (nextFile.size >= 262144) { // 256kb result.innerHTML += '<div class="f">Too big file (max filesize exceeded)</div>'; handleComplete(nextFile.size); } else { uploadFile(nextFile, status); } } else { dropArea.className = ''; } } initHandlers(); })();
Большая часть кода уже прокомментирована. Я надеюсь, что вы можете понять весь этот код. В любом случае — некоторое объяснение того, как это работает: в начале мы связали два обработчика с нашей DropArea: «drop» и «dropover». Когда мы помещаем перетаскиваемые файлы в область перетаскивания, мы можем применять собственные стили к нашей области перетаскивания. Затем, когда мы отбрасываем наши файлы, наш скрипт начинает выполнять функцию ‘processFiles’ (она помещает все отброшенные файлы в массив и начинает их загрузку шаг за шагом). В результате мы отправляем данные через объект XMLHttpRequest на пользовательский сервер получателей. Во время отправки файлов мы также отображаем общий прогресс в нашем элементе canvas.
Шаг 4. PHP
upload.php
<?php // set error reporting level if (version_compare(phpversion(), '5.3.0', '>=') == 1) error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED); else error_reporting(E_ALL & ~E_NOTICE); function bytesToSize1024($bytes, $precision = 2) { $unit = array('B','KB','MB'); return @round($bytes / pow(1024, ($i = floor(log($bytes, 1024)))), $precision).' '.$unit[$i]; } if (isset($_FILES['myfile'])) { $sFileName = $_FILES['myfile']['name']; $sFileType = $_FILES['myfile']['type']; $sFileSize = bytesToSize1024($_FILES['myfile']['size'], 1); echo <<<EOF <div class="s"> <p>Your file: {$sFileName} has been successfully received.</p> <p>Type: {$sFileType}</p> <p>Size: {$sFileSize}</p> </div> EOF; } else { echo '<div class="f">An error occurred</div>'; }