Загрузка изображений без перезагрузки страницы

Вступление

Почти все сайты сейчас в первую очередь направлены на производительность и удобный пользовательский интерфейс. Загрузка изображений без перезагрузки страницы одно из таких удобств.

Пример загрузки файлов без перезагрузки + готовый архив с примером для скачивания.

Пример ниже реализован на PHP+Ajax.

Понадобится

PHP, JavaScript и iframe. А так же 5 файлов: index.php, ajax.js, upload.js, upload.php, list.php и папка для загрузки изображений, в данном примере ./img/

index.php — форма загрузки изображения

В этом файле создается форма, инпут типа файл и скрытый ифрейм.

<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>AJAX-загрузка изображений без перезагрузки страницы</title> <style type="text/css"> h1 {font-weight:normal; font-family:Georgia, serif; font-size:20pt;} iframe {width:0; height:0; border:0;} hr {clear:both; border:0; background-color:#CCC; height:1px;} </style> <script type="text/javascript" src="ajax.js"></script> <script type="text/javascript" src="upload.js"></script> </head> <body onLoad="Upload.updateImagesList();"> <form onsubmit="return Upload.upload()" method="post" action="./upload.php" enctype="multipart/form-data" id="upload_image_form" target="upload_image_iframe"> <input type="hidden" name="MAX_FILE_SIZE" value="512000"> <h1>Загрузка изображений без перезагрузки страницы</h1> <p>Выберите файл с JPEG-изображением, не более 500Кб</p> <p><input type="file" name="image" id="upload_image_file"></p> <p><input type="submit" value="Загрузить изображение" id="upload_image_submit"></p> </form><hr> <p><a href="./clear.php">Удалить изображения</a></p> <div id="layer_images_list">Нет изображений</div> <iframe name="upload_image_iframe" id="upload_image_iframe"></iframe> </body></html>

ajax.js

Данные файла упоминался в статье Как правильно послать запрос (Ajax).

/** * Класс для отправки асинхронных запросов, AJAX * * Автор: Федоров Артем * Сайт: http://artemfedorov.ru * */ Ajax = function(url, method, vars, encoding, callback, responsetype) { this.xmlHttpRequest = null; this.ajax = this; this.buffer = null; this.url = url || false; this.method = method || 'GET'; this.vars = vars || null; this.encoding = encoding || 'utf-8'; this.onReady = callback || null; this.responseType = responsetype || 'xml'; /** * type of return * */ this.setResponseType = function(type) { this.responseType = type; } /** * To set url for ajax connection * */ this.setUrl = function(url) { this.url = url; } /** * Set method: POST|GET * */ this.setMethod = function(method) { this.method = method; } /** * Set vars * */ this.setVars = function(vars) { this.vars = vars; } /** * Set encoding * */ this.setEncoding = function(encoding) { this.encoding = encoding; } /** * Check for errors * */ this.isError = function() { return false; } /** * Try to set url connection * */ this.connect = function() { var url = this.url; var method = this.method; var vars = this.vars; var encoding = this.encoding; if (this.xmlHttpRequest != null) { this.xmlHttpRequest.open(method, url, true); this.xmlHttpRequest.onreadystatechange = function(ajax) { return function() { ajax._progressResponse(ajax.xmlHttpRequest, ajax.responseType); } } (this); this.xmlHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset-"+encoding); this.xmlHttpRequest.send(vars); } } /** * To progress response to url * */ this._progressResponse = function(xmlhttprequest, responsetype) { var value; if ( xmlhttprequest.readyState == 4 ) { if (xmlhttprequest.status == 200 && this.onReady != null) { switch (responsetype) { case 'text': value = xmlhttprequest.responseText; break; case 'xml': default: value = xmlhttprequest.responseXML; break; } this.onReady(value); } else { if (this.onReady == null) { alert('Не определена функция Ajax.onReady'); } } } } /** * Create http request * */ this._createXmlHttpRequest = function() { if (window.XMLHttpRequest) { this.xmlHttpRequest = new XMLHttpRequest(); if (this.xmlHttpRequest.overrideMimeType) { this.xmlHttpRequest.overrideMimeType('text/xml'); } } else if (window.ActiveXObject) { try {this.xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");} catch(e) { try {this.xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");} catch(e){;} } } } this._createXmlHttpRequest(); }

upload.js

Файл начинает загрузку изображения и проверяет по таймеру статус загрузки изображения.

/** * Объект для загрузки изображений без перезагрузки страницы * * Автор: Федоров Артем * Сайт: http://artemfedorov.ru * */ var Upload = { isInit: false, error: '', iframe: null, imagesListLayer: null, inputFile: null, form: null, opts: { timeout: null, start: false, iframe: null, loaderImage: null }, // инициализация основных опций init: function() { if (!this.isInit) { this.isInit = true; this.imagesListLayer = document.getElementById('layer_images_list'); this.inputFile = document.getElementById('upload_image_file'); this.form = document.getElementById('upload_image_form'); } }, // обновление списка изображений updateImagesList: function() { this.init(); var ajax = new Ajax(); ajax.setUrl('./list.php'); ajax.setMethod('GET'); ajax.onReady = function(upload) { return function(xml) { upload.xmlParseImages(xml); } }(this); ajax.connect(); }, // Калбак функция для обработки XML (обработка списка изображений) xmlParseImages: function(xml) { var i, a, img, images, image, img, divBg; images = xml.getElementsByTagName('image'); this.imagesListLayer.innerHTML = images.length == 0 ? 'Изображений нет' : ''; for (i=0; i<images.length; i++) { var img = new Image(); img.align = 'left'; img.height = 200; img.src = images[i].getAttribute('src'); this.imagesListLayer.appendChild(img); } }, // Загрузить изображение upload: function() { this.init(); var status='', p; if (this.inputFile.value == '') this.error += "Вы не выбрали файл\r\n"; if (/\.(jpg|jpeg)/i.test(this.inputFile.value) != true) this.error += "Файл должен иметь расширение .jpg или .jpeg\r\n"; if (this.error != '') { alert(this.error); this.error = ''; return false; } else { this.error = ''; } if (!this.opts.start) { this.opts.start = true; this.opts.iframe = document.getElementById('upload_image_iframe'); } status = this.checkUploadStatus(); switch (status) { case '0': this.resetUpload(); this.updateImagesList(); return true; break; case 'NULL': case '1': case '2': this.error += "Файл превысил 500Кб\r\n"; alert(this.error); this.resetUpload(); break; case '3': case '4': this.error += 'Файл не был загружен\r\n'; alert(this.error); this.resetUpload(); break; case '5': this.error = 'Файл должен быть JPG\r\n'; alert(this.error); this.resetUpload(); break; default: document.getElementById('upload_image_submit').disabled = true; document.getElementById('upload_image_submit').value = 'Подождите, идет загрузка...'; this.opts.timeout = setTimeout(function(upload) { return function() { return upload.upload(); } }(this), 100); break; } }, // Проверка статуса загрузки изображения checkUploadStatus: function() { return this.opts.iframe.contentWindow.document.body.innerHTML; }, // Обновить форму загрузки изображений resetUpload: function() { this.error = ''; clearTimeout(this.opts.timeout); this.opts.iframe.contentWindow.document.body.innerHTML = ''; this.opts.start = false; this.form.reset(); document.getElementById('upload_image_submit').disabled = false; document.getElementById('upload_image_submit').value = 'Загрузить изображение'; } }

upload.php — файл загрузки изображения

Принимает запрос на загрузку изображения и выводит на экран 0 — если файл успешно загружен, 1,2 — если размер файла превысил допустимый лимит, 3,4 если произошла какая-то другая ошибка, 5 — файл не является JPEG.

<?php if (isset($_FILES['image'])) { if ($_FILES['image']['type']!='image/jpg'&&$_FILES['image']['type']!='image/jpeg'&&$_FILES['image']['type']!='image/pjpeg') { echo '3'; } elseif ($_FILES['image']['error'] == 0) { $filename = './img/'.md5(uniqid(rand(), true)).'.jpg'; while (file_exists($filename)) { $filename = './img/'.md5(uniqid(rand(), true)).'.jpg'; } move_uploaded_file($_FILES['image']['tmp_name'], $filename); echo '0'; } else { echo $_FILES['image']['error']; } } else { echo '2'; } ?>

list.php — список изображений

Файл генерирует XML-документ, который содержит список изображений, загруженных в папку ./img/.

<?php header('Content-type: text/xml; charset=utf-8;'); echo '<?xml version="1.0" encoding="utf-8"?><images>'; $images = scandir('./img/'); foreach ($images as $image) { if ($image != '.' && $image != '..') echo '<image src="img/'.$image.'" />'; } echo '</images>'; ?>

Как это работает

POST-запрос на загрузку файла(upload.php), отправляется в скрытый iframe, где и будет выведен результат загрузки. После чего javascript-функция Upload.upload() по таймеру начинает проверку содержимого скрытого ифрейма.

upload.php может вывести 5 результатов: 0 — файл успешно загружен, 1,2 — если размер файла превысил допустимый лимит, 3,4 если произошла какая-то другая ошибка, 5 — файл не является JPEG.

Если результат равен 0, то через аякс обновляется список загруженных изображений, если другой результат — выводится соответствующая номеру ошибка.

Заключение

Многие называют это AJAX-загрузкой файлов, но на самом деле было бы правильней сказать — iframe-загрузка, т.к. при помощи аякса только получается список изображений.

Советую еще раз посмотреть пример работы или скачать готовый архив с примером.

Категории

ПрограммированиеJavaScriptAjax

Читайте также

Комментарии

Владислав Омельчук

Каким образом можно реализовать полосу загрузки файла?

Ответить
Никита Пушкарь

Добрый день!
А что нужно изменить, чтобы под каждой картинкой появлялось "удалить", то есть чтобы можно было удалять по одной картинке а не все сразу?

Ответить