Загрузка файлов с помощью SWFUpload и PHP

14 августа, 2010
swfupload

О загрузке файлов на сервер рассказывается, наверное, в каждой книге о веб разработке. Обычно при этом приводится пример формы с тегом input type=file и объясняется, как работать с массивом $_FILES на стороне сервера. Это классический вариант. Он отлично работает, но имеет несколько ограничений.

1) Чтобы загрузить несколько файлов, нужно создать несколько тегов input. При этом пользователь должен будет выбирать каждый файл отдельно, что довольно неудобно при большом количестве файлов.

2) Невозможно показать процент загрузки файла.

3) Загрузка нескольких файлов будет выполнена в одном запросе. Тут нет ничего плохого, но может возникнуть проблема, если на сервере установлены ограничения на максимальный объем запросов и время выполнения скриптов.

4) Загрузка не будет асинхронной, т.е. произойдет перезагрузка страницы.

На сегодняшний день существует два основных варианта решения этих проблем. Использование iframe или flash (по-идее, silverlight тоже можно использовать для этих целей).

Кстати, о решении с помощью iframe я раньше рассказывал (Как реализовать асинхронную загрузку файлов с помощью JavaScript и PHP).

Сегодня речь пойдет об использовании flash, а точнее библиотеки SWFUpload.

На мой взгляд, это одно из лучших решений, т.к. несмотря на то, что отправка файлов осуществляется с помощью flash, настройка, управление и отслеживание процесса загрузки выполняется с помощью JavaScript.

Пересказывать возможности SWFUpload я не буду, просто покажу небольшой пример её использования.

Постановка задачи.

Допустим нам необходимо позволить пользователю загружать фотографии на сервер. При этом, сразу после загрузки они должны появляться внизу страницы.

Шаг 1. Создаём главную страницу (index.php).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>
    <title>SWFUpload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <h1>SWFUpload</h1>
    <div id="uploadButton"></div>
    <div id="status"></div>
    <div id="images"></div>
    <script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
    <script type="text/javascript" src="js/swfupload.js"></script>
    <script type="text/javascript" src="js/plugins/swfupload.queue.js"></script>
    <script type="text/javascript" src="js/main.js"></script>
</body>
</html>

Здесь мы создали три блока.

uploadButton – предназначен для размещения кнопки загрузчика.

status – здесь мы будем выводить сообщения о процессе загрузки.

images – в этом блоке будут показаны загруженные картинки.

В конце страницы подключены 4 js файла.

Первый – библиотека jquery (её использовать необязательно, я просто хотел немного сократить количество js кода в примере).

Второй – swfupload.js. Это основной скрипт библиотеки SWFUpload. Именно он создаёт кнопку загрузки.

Третий – plugins/swfupload.queue.js. Тоже входит в состав библиотеки. Позволяет загружать несколько файлов одновременно.

Четвёртый – main.js. Здесь находится код настройки библиотеки и обработчики событий. Его мы сейчас и рассмотрим.

Шаг 2. Настраиваем SWFUpload.

Для того, чтобы подключить библиотеку, нужно создать объект SWFUpload и передать ему хеш с настройками.

Делается это следующим образом (код из файла main.js).

var swfu = new SWFUpload(
	{
		upload_url : "upload.php",
		flash_url : "swfupload.swf",
		button_placeholder_id : "uploadButton",

		file_size_limit : "2 MB",
		file_types : "*.jpg; *.png; *.jpeg; *.gif",
		file_types_description : "Images",
		file_upload_limit : "0",
		debug: false,

		button_image_url: "button.png",
		button_width : 100,
		button_height : 30,
		button_text_left_padding: 15,
		button_text_top_padding: 2,
		button_text : "<span class=\"uploadBtn\">Обзор...</span>",
		button_text_style : ".uploadBtn { font-size: 18px; font-family: Arial; background-color: #FF0000; }",

		file_dialog_complete_handler : fileDialogComplete,
		upload_success_handler : uploadSuccess,
		upload_complete_handler : uploadComplete,
		upload_start_handler : uploadStart,
		upload_progress_handler : uploadProgress
	}
);

Думаю, названия большинства параметров говорят сами за себя, но хочу обратить ваше внимание на некоторые моменты.

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

С помощью параметров flash_url и button_placeholder_id указываем адрес флеш ролика, который создаёт кнопку загрузки и id элемента на странице, в котором эта кнопка будет размещена.

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

После этого указываем параметры, настраивающие внешний вид кнопки загрузки. Эта часть обязательная, т.к. по-умолчанию кнопка имеет размер 1х1 пиксель, и пользоваться ей будет невозможно.

Т.к. кнопка представляет собой флеш ролик, оформить её напрямую с помощью CSS не получится, но с помощью этих параметров вы можете указать фоновую картинку, шрифт и положения текста.

Оставшиеся параметры устанавливают обработчики событий. Рассмотрим их подробнее.

function uploadSuccess(file, serverData) {
	$('#images').append($(serverData));
}

function uploadComplete(file) {
	$('#status').append($('<p>Загрузка ' + file.name + ' завершена</p>'));
}

function uploadStart(file) {
	$('#status').append($('<p>Начата загрузка файла ' + file.name + '</p>'));
	return true;
}

function uploadProgress(file, bytesLoaded, bytesTotal) {
	$('#status').append($('<p>Загружено ' + Math.round(bytesLoaded/bytesTotal*100) + '% файла ' + file.name + '</p>'));
}

function fileDialogComplete(numFilesSelected, numFilesQueued) {
	$('#status').html($('<p>Выбрано ' + numFilesSelected + ' файл(ов), начинаем загрузку</p>'));
	this.startUpload();
}

Сразу хочу обратить ваше внимание. В этом примере использованы не все события, более полные примеры вы найдете на официальном сайте библиотеки.

Начнем с события file_dialog_complete. Оно возникает, когда пользователь выбирает файлы и нажимает кнопку «Open». В его обработчике (fileDialogComplete) вам обязательно нужно запустить загрузку (сама по себе она не начнётся!).

this.startUpload();

Также обратите внимание, что обработчик события upload_start должен возвращать true, для того, чтобы загрузка началась.

Большинство из приведённых здесь обработчиков, получают объект file в первом параметре. Как несложно догадаться в нём содержится информация о загружаемом файле. Имя файла можно получить так – file.name.

Ещё один интересный момент – разница между событиями upload_success и upload_complete. Первое срабатывает после того, как flash ролик завершает отправку файла, второе – после того как приходит ответ сервера. Учтите, что если вы после загрузки картинки на сервер будете выполнять её обработку (масштабирование, например), то задержка между этими событиями будет заметной.

В данном случае сервер просто возвращает тег img для загруженной картинки.

Шаг 3. Создаём серверный скрипт (upload.php).

<?php

$uploadDir = 'uploads/'; //папка для хранения файлов

$allowedExt = array('jpg', 'jpeg', 'png', 'gif');
$maxFileSize = 2 * 1024 * 1024; //1 MB

//если получен файл
if (isset($_FILES)) {
    //проверяем размер и тип файла
    $ext = end(explode('.', strtolower($_FILES['Filedata']['name'])));
    if (!in_array($ext, $allowedExt)) {
        return;
    }
    if ($maxFileSize < $_FILES['Filedata']['size']) {
        return;
    }
    if (is_uploaded_file($_FILES['Filedata']['tmp_name'])) {
        $fileName = $uploadDir.$_FILES['Filedata']['name'];
		//если файл с таким именем уже существует...
        if (file_exists($fileName)) {
            //...добавляем текущее время к имени файла
            $nameParts = explode('.', $_FILES['Filedata']['name']);
            $nameParts[count($nameParts)-2] .= time();
            $fileName = $uploadDir.implode('.', $nameParts);
        }
        move_uploaded_file($_FILES['Filedata']['tmp_name'], $fileName);
        echo '<img src="'.$fileName.'" alt="'.$fileName.'" />';
    }
}

В принципе, это один из самых простых вариантов скрипта загрузки файлов. Я уже упоминал, что SWFUpload отправляет файлы в отдельных запросах, поэтому в массиве $_FILES может быть только один файл.

Вначале скрипта указываем папку для загрузки файлов, допустимые расширения и размер. Эти же параметры указаны и при настройке flash загрузчика, но напоминаю, что доверять полученным от клиента данным нельзя.

Затем выполняем проверки (строки 11-18) и с помощью функции move_uploaded_file копируем загруженный файл в указанную папку.

Если файл с таким же именем уже был загружен, то добавляем к имени файла текущее время.

После этого, формируем тег img и отправляем его браузеру.

Как видите, ничего сложного. Использование библиотеки сводит количество вашего кода к минимуму. Хотя, если вы захотите создать красивый интерфейс, наглядно иллюстрирующий процесс загрузки, то поработать всё же придется ;)

Если хотите поэкспериментировать, качайте архив с этим примером.

архив с исходным кодом

Вы можете распаковать его в любую папку на вашем сервере. Только убедитесь, что папка uploads доступна для записи.

Будут вопросы или замечания – пишите!

Удачи!

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в HTML, JavaScript, PHP, Web разработка Комментарии (119) »

]]>

Вы можете оставить комментарий. Трекбеки закрыты.

  • http://twitter.com/theBuCeFaL Denis Medved

    Спасибо =)

  • Игорь

    Спасибо за статью. Никогда не возникало ошибки 2038 при аплоаде нескольких файлов?

  • http://ok-podarok.ru Bong Master

    Объясните зачем загружать через SWFUpload или PHP когда есть куча FTP клиентов, которые все сделают быстро и без ошибок :-)

    • http://fafka.ru Anon

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

  • http://twitter.com/theBuCeFaL Denis Medved

    пример задачи:
    есть форма через которую пользователь заливает картинки. К-во картинок выберает пользователь.
    (к примеру фотоальбом ВКонтакте).
    По 1 файлу(фотке) выбирать напряжно.
    + прогрес бар , красота …

  • Pingback: Дайджест за тиждень. Випуск №6, 20 серпня | Блоґ Виспянського Ігоря

  • http://int-estate.com/ troy

    Очень удобно, спасибо!

  • http://www.glory-models.com Denys

    Привет!
    А как несколько кнопочек-загрузчиков разместить на странице?

    Подскажите, пожалуйста, буду очень благодарен!

    Спасибо!

  • seomoney

    Спасибо. Очень удобно и практично!

  • http://www.simplecoding.org Владимир

    Ошибки были, не уверен, что именно 2038, т.к. flash "падал" полностью.
    Убрал в настройках swfupload режим отладки.
    debug: false
    После этого проблемы исчезли.

  • http://www.simplecoding.org Владимир

    1) Если вы не хотите или не можете предоставить ftp доступ.

    2) Если нужно выполнять какие-нибудь действия после загрузки файлов, например, создание миниатюр для картинок.

  • http://www.simplecoding.org Владимир

    Я лучше дам ссылку на готовый пример
    http://demo.swfupload.org/v220/multiinstancedem…

    Общая идея такая
    upload1 = new SWFUpload({
    //настройки для загрузчика 1
    })

    upload2 = new SWFUpload({
    //настройки для загрузчика 2
    })

  • orcoved

    Спасибо за статью и ссылки!
    Подскажите как сделать так чтобы фотки выводились по 3 штуки в строке?
    Я пробовал так:
    <div id="uploadButton"></div>
    <div id="status"></div>
    <div id="images" width="400px"></div>

    и так:
    <div id="uploadButton"></div>
    <div id="status"></div>
    <table id="images" width="400px"></table>

    и так:
    <div id="uploadButton"></div>
    <div id="status"></div>
    <table width="400px">
    <div id="images"></div>
    </table>

    Но все равно фотки грузятся в 1 строку ((

  • http://www.simplecoding.org Владимир

    Если вы используете таблицу, то где теги td и tr ?
    Если без таблицы (внутри div), то все зависит от размера фотографий. Вы задаете общую ширину 400px, значит ширина изображений должны быть не более 133px.
    Просто добавляйте теги img внутрь div.

    • Freddyblazin

      фотки

      • Frankenstein

        прошу прощения, не block, a inline-block;

        • http://www.simplecoding.org Владимир

          inline-block к какому элементу применяется?

  • Anonimous

    А меня интересует другой аспект:
    файлы загружаются флешкой. Флешка выполняется хоть и в браузере, но как бы с компа – тобишь даже если пользователь авторизовался на сайте, флешка (флеш-аплоадер, расположенный на этом сайте) не знает об этом — не посылает куки. Или это у меня глюк?

    А чтобы серверная часть заработала, приходится отключать проверку авторизации, а в этом случае пользователь может подменить данные и, например, загруженные им картинки присвоить другому юзеру и т.п…

    Как вы выкручиваетесь? Или это я что-то сделал не так?

    • http://www.simplecoding.org Владимир

      Нет, эта проблема не только у вас.Обсуждение можно почитать здесь.Кроме того, есть страница, демонстрирующая этот баг -http://demo.swfupload.org/v220/cookiebugdemo/index.phpТакже в дистрибутив входит плагин swfupload.cookies.js, которыйавтоматически собирает все cookie и добавляет их в post_params.

      • http://www.facebook.com/zhenya.shevchenko Zhenya Shevchenko

        А можно попросить продублировать ссылку на обсуждение или возможные решения? Что-то я не могу разобраться как заставить COOKIE работать под IE.

  • http://aleks-gold.ru/ Aleks-Gold

    Не плохо, сегодня попробую этот метод на деле)

  • Andrey

    Полезная статья. Но у меня возник вопрос: можно ли скрыть флешовую кнопку, и вызвать диалог выбора файлов с помощью JS?

  • Andrey

    Полезная статья. Но у меня возник вопрос: можно ли скрыть флешовую кнопку, и вызвать диалог выбора файлов с помощью JS?

    • Andrey

      Пробовал swfu.getMovieElement().SelectFiles()
      Не работает :=(
      Может я что то делаю не так, или это в принципе не предусмотрено?

      • http://www.simplecoding.org Владимир

        В документации насчет selectFiles() сказано

        Deprecated. Not compatible with Flash Player 10.

        Готового метода для открытия окна я не нашел. Но, наверное, вам лучше задать этот вопрос специалисту по флешу.

  • Nabla

    Привет! Очень хорошая статья – наконец-то нашел, что хотел.
    Но.
    Мне не нравится само отображения процесса загрузки.
    Например:
    Выбрано 1 файл(ов), начинаем загрузку
    Начата загрузка файла slezy remix.mp3
    Загружено 0% файла slezy remix.mp3
    Загружено 3% файла slezy remix.mp3
    Загружено 4% файла slezy remix.mp3
    Загружено 6% файла slezy remix.mp3
    Загружено 7% файла slezy remix.mp3
    Загружено 8% файла slezy remix.mp3

    Как это можно изменить?
    Хотелось бы, чтобы обновлялась строчка – а не создавались новые строчки.

    • http://www.simplecoding.org Владимир

      Измените uploadProgress. Вместо append используйте html.Например$('#status').html($('Загружено ' + Math.round(bytesLoaded/bytesTotal*100) + '% файла ' + file.name + ''));

  • Flame

    Здравствуйте, возможно вы сможете помочь….
    SWFUpload – проблема в следующем маленькие файлы грузит на ура! а вот с файлами более 2MB работать отказывается, аякс работает проценты пробегают, но вот перемещения не происходит (по всей видимости с функцией move_uploaded_file проблемы или в флэшэ может быть зашито ограничение)…..
    Объём разрешенных файлов в файлах сменил….
    upload.php
    <?php
    set_time_limit(0);
    $uploadDir = '../uploads/';
    $allowedExt = array('jpg', 'jpeg', 'png', 'gif');
    $maxFileSize = ((2 * 1024) * 1024) * 1024;
    if (isset($_FILES)) {
    $ext = end(explode('.', strtolower($_FILES['Filedata']['name'])));
    if (!in_array($ext, $allowedExt)) {
    return;
    }
    if ($maxFileSize

    main.js
    $(document).ready(function() {
    function uploadComplete(file) {
    $('#status').html($('Загрузка завершена'));
    }
    function uploadStart(file) {
    $('#status').html($('Начата загрузка файла ' + file.name + "));
    return true;
    }
    function uploadProgress(file, bytesLoaded, bytesTotal) {
    $('#status').html($('Загружено ' + Math.round(bytesLoaded/bytesTotal*100) + '% '));
    }
    function fileDialogComplete(numFilesSelected, numFilesQueued) {
    $('#status').html($('Выбрано ' + numFilesSelected + ' файл(ов), начинаем загрузку'));
    this.startUpload();
    }
    var swfu = new SWFUpload(
    {
    upload_url : "SWFUI/upload.php",
    flash_url : "SWFUI/swfupload.swf",
    button_placeholder_id : "uploadButton",
    file_size_limit : "100000 MB",
    file_types : "*.jpg; *.png; *.jpeg; *.jpg; *.gif; *.JPG; *.PNG; *.JPEG; *.JPG; *.GIF;",
    file_types_description : "Файлы",
    file_upload_limit : "0",
    button_image_url: "SWFUI/button.png",
    button_width : 160,
    button_height : 23,
    button_text_left_padding: 10,
    button_text_top_padding: 1,
    button_text : "Загрузить файл(ы)…",
    button_text_style : ".uploadBtn { font-size: 14px; font-family: Arial; font-color: #0a412d; }",
    file_dialog_complete_handler : fileDialogComplete,
    upload_complete_handler : uploadComplete,
    upload_start_handler : uploadStart,
    upload_progress_handler : uploadProgress
    }
    );
    });
    убрал некоторые не нужные вещи что с ними что без них не перемещает более 2 MB

    • Andrey

      В php.ini есть ограничение
      upload_max_filesize = 2M
      Подправьте ini файл, если есть к нему доступ, или в upload.php в начале добавьте
      ini_set("upload_max_filesize", "32M");
      Вместо 32mb желаемую величину.

      • SavenetsNN

        а как сделать функционал для отмены загрузки?

        • SavenetsNN

          И еще, почему Не могу при неправильном размере показать ошибку юзерам. Последнее что происходит это this.startUpload(); После этого концы теряются. не привета не ответа. Подскажите пожалуйста как побороть

          А так ваш скрипт бомба хотябы можна разобраться нормально, не то что офф примеры. ппц (два дня насмарку)

        • http://www.simplecoding.org Владимир

          Есть две функции cancelUpload и stopUpload. Думаю, одна из них вам подойдет.

          Насчет ошибки ничего конкретного сказать не могу. По-идее, должно возникать событие uploadError. Попробуйте поменять версию плагина, обновить flash и т.д.

        • SavenetsNN

          еще вопросик. как бы мне с бекенда upload.php возвращать json объект. пробовал в upload.php писать
          $name,
          'type' => $type
          );

          echo json_encode($json);
          ?>

          не могу никак в main.js его принять пробовал eval или просто serverData.name не выходит

          Подскажите пожалуйста если можна на примере потому что перепробовал пару возможных вариантов пишет undefined

        • http://www.simplecoding.org Владимир

          Смотрите firebug'ом что приходит от сервера. Потому что код, который вы привели, правильный.

        • Vic

          Для IE обязательно нужно выдавать заголовок, например
          header("Content-type:text/plain; charset=utf-8");

  • http://murzilka.biz/ Дмитрий

    У меня возникла проблема загрузки видео файлов с использованием SWFUpload в CodeIgniter. Может, кто сталкивался? Подскажите, пожалуйста. Там нужно добавить mime типы правильные.

    • http://www.simplecoding.org Владимир

      С такой проблемой сталкивался, правда, довольно давно.
      По-моему, я просто вывел содержимое массива
      $this->upload->data() и в нем посмотрел mime тип, который передается браузером. После этого просто прописал этот тип в allowed_types. В config/mimes.php есть массив со всеми типами.

      И еще, желательно проверять работу загрузчика в нескольких браузерах, т.к. mime тип может меняться. Хотя в данном случае этого не должно происходить, т.к. отправка осуществляется с помощью flash.

      • http://murzilka.biz/ Дмитрий

        Спасибо, Владимир. Буду разбираться.

  • Flame

    Здравствуйте снова :)
    Andrey с размерами файлов разобрался СПАСИБО БОЛЬШОЕ!, но нарисовалась новая проблема а именно с сессиями, скрипт под названием upload.php не в какую не хочет запускать сессию и брать оттуда данные… как-то можно решить эту проблему, очень нужно…..

    • Andrey

      Нужно передавать параметры сессии через POST, для этого нужно добавить
      var swfu= new SWFUpload({

      post_params: {"": ""},

      })

      • Andrey

        там были PHP теги, при добавлении коммента обрезались
        post_params: {"session_name()": "session_id"}

        • http://www.simplecoding.org Владимир

          Я дополню ответ ссылкой на решение для CI.

        • Flame

          Andrey, Владимир – Огромное вам спасибо! :) очень выручили к тому же ещё небольшой багаж знаний дали в придачу :)

        • Iam

          для этого надо код создания аплоадера вынести из main.js в какой-либо php исполняемый шаблон

  • SavenetsNN

    А как добавить параметр serverData в функцию
    function uploadComplete(file) ???

    Подскажите очень надо!

    • http://www.simplecoding.org Владимир

      Обработчкик uploadComplete параметр serverData не передается, поэтому напрямую получить его нельзя. Но можно сделать так:

      1) Установить обработчик uploadSuccess (он будет вызван ранее uploadComplete и получит serverData).

      2) В этом обработчике (uploadSuccess) присвоить serverData какой-нибудь глобальной переменной (объявлена за пределами обработчика, можно объявить ее в самом начале скрипта).

      3) В обработчике uploadComplete прочитать данные из этой переменной.

  • Zimpsonz

    Вот проблемка не получается вывести имя файла функцией echo
    . Подскажите в какой переменной хранится само имя, все перепробовал и не выводит=(

    • http://murzilka.biz/ Дмитрий

      В массиве $_FILES

      • Xtra

        никак не вывести echo со ссылкой на файл :(

        • http://www.simplecoding.org Владимир

          Сделайте var_dump($_FILES) ;)

  • usp

    А у меня не загружаются файлы размером больше 8 мегабайт. В php ini ограничение стоит 2 GB, а в swfuploader'e file_size_limit : "2048 MB".
    Не понимаю, в чем дело, может, кто сталкивался?

    • http://murzilka.biz/ Дмитрий

      У меня тоже была такая проблема. Посмотрите в php.ini переменную post_max_size

    • Sulatskov Vladimir

      php.ini
      Параметры : upload_max_filesize и post_max_size.

    • Gagaevmark

      у вас скорее всего в настройках сервера стоит не более 8 мб. какой у вас сервер?

      • Gagaevmark

        сорри спросонок, в настройках пхп

  • Reddog

    Спасибо :)

  • Dema

    А как сделать чтобы ф-л upload.php введенный через строку браузера (напр. ввв.сайт.ру/upload.php) не выполнялся?

    • http://www.simplecoding.org Владимир

      Для данного примера – никак, т.е. если вы запретите его выполнение, то и файлы загружаться не будут.
      Просто проверяйте в upload.php все значения и выдавайте соответствующий ответ.

    • Andrey

      В начале upload.php добавить:
      if(!$_FILES) exit("there is no uploaded files");

  • codefather

    Спасибо за статью
    вопрос
    а можно ли в интерфейс добавить текстовое поле, что вместе с файлом (или уже после загрузки) передавать дополнительный параметр, например, alt для картинки?

    • http://www.simplecoding.org Владимир

      Да, можно.
      Добавьте обычное текстовое поле. Далее, в uploadComplete (вызывается после успешной загрузки файла) добавляете отправку ajax запроса в котором и передайте нужный текст.
      Естественно, на сервере должен быть скрипт, который обработает запрос и сохранит текст в БД.

      • Iam

        да
        спасибо. так и сделал.
        кстати, что странно
        не обрабатываются ошибки
        например, если upload php нет в принципе, весь процесс проходит якобы успешно, разве только uploadComplete не происходит. диагностики нет

        • Iam

          добавлю вопрос
          а как правильно дебажить?
          вот я правлю upload.php
          заменяю странные if ($maxFileSize < $_FILES['Filedata']['size']) {
          return;
          }
          на
          die ('too big file');

          а как теперь в клиенте поймать это сообщение?

        • http://www.simplecoding.org Владимир

          Вообще, есть специальные программы – снифферы, которые позволяют анализировать весь сетевой трафик.

          Но часто удобнее просто вести лог на сервере. Большинство фреймворков имеет встроенные библиотеки для ведения логов. Если фреймворк не используется, можно попробовать эту библиотеку (на освоение уйдет минут 10).

    • Andrey

      Через пост параметры
      swfu.addPostParam("name", "value");

  • http://www.facebook.com/profile.php?id=100000796506276 Андрюс Сурвила

    Большое спасибо, рабочий пример.
    Возникает только сложность с загрузкой файла например: 1 Canto para limpiar malas energias y diablos.mp3
    swfup говорит, что все загружено, а на серваке ничего не появляется.
    в $_FILE пусто
    при этом с другими файлами такого не возникает, даже с таким "2 типа 2.mp3"

    • http://www.simplecoding.org Владимир

      Проверьте размер файла, во втором листинге, строка 7 установлено ограничение
      file_size_limit : "2 MB",

  • Xpaco

    Огромное человеческое спасибо :)
    -Programax Team http://www.progra-max.ru

  • Xaoc-

    Приятный сайт у Вас :)
    Подскажите, может ли этот аплоадер загружать не только изображения но и файлы другого типа? (*.rar, *.psd)? И если да, то как это реализовать?

    • Xaoc-

      Так, разобрался как с *.rar, не могу понять почему тоже самое не прокатывает с *.psd??

      • http://www.simplecoding.org Владимир

        Уточните, пожалуйста. psd файл не отправляется на сервер или не принимается сервером? Не понятно где искать проблему, в настройках swf uploader или есть какие-то ограничения на стороне сервера.

  • Роман

    Выводится только надпись SWFUpload. Что делать?

    • http://www.simplecoding.org Владимир

      Посмотреть firebug'ом какие запросы были отправлены и какие скрипты загрузились.

  • Sergserg1

    Спасибо за статью!!!
    Я исп

    Я использую этот скрипт для выгрузки на сервер фото и отображения их в ДИВе с ID «thumbnails». Нужно что бы рядом с каждым фото появлялась маленькая кнопочка или ссылка при нажатии, на которую загруженное фото удаляется.

    На одном сайте нашел реально работающий скрипт удаления

    function addImageToMaxCount(){
    var oldVar = parseInt(swfu.getSetting('file_upload_limit'));
    if (isNaN(oldVar)) oldVar = 0;
    var newVal = oldVar + 1;
    swfu.setFileUploadLimit(newVal);
    swfu.setFileQueueLimit(newVal);
    }
    $('#thumbnails a').click(function(){
    $.ajax({
    url: $(this).attr('href'),
    cache: false
    });
    $(this).parent().remove();
    addImageToMaxCount();
    return false;
    });

    Сам скрипт загрузки выглядит примерно так

    var swfu;
    var sid = 'rql399h93i64ijcmdttsnqqdv1';
    $(document).ready( function () {
    var maxUpload = parseInt('5') – $('#thumbnails .uploadsList').size();
    if (maxUpload < 1) maxUpload = 'null';
    swfu = new SWFUpload({
    // Backend Settings
    upload_url: "/uploadphoto.php",….
    ….
    file_upload_limit : maxUpload,
    file_queue_limit : maxUpload,…

    Но у меня функция удаления не работает, поскольку я не знаю, как сделать так чтобы в ДИВе thumbnails в процессе загрузки фотографий появлялись тэги a с атрибутами attr('href')и элементами parent(). Функцию удаления должен вызывать JQuery при клике на $('#thumbnails a')

    • http://www.simplecoding.org Владимир

      Вы не сможете удалить файл на сервере с помощью только JavaScript.
      Нужен серверный скрипт (PHP), который и будет удалять файлы.

      • Sergserg1

        Владимир,
        Если Вы внимательно посмотрите на код функции удаления, а именно на фрагмент
        $('#thumbnails a').click(function(){
        $.ajax({
        url: $(this).attr('href'),
        cache: false
        });
        $(this).parent().remove();
        addImageToMaxCount();
        return false;
        });
        То увидите, что JavaScript на сервере ничего не удаляет, а обнуляет на клиенте атрибут href для тега и удаляет родительский для него контейнер $(this).parent().remove() которым очевидно является картинка thumbnail
        Все эти манипуляции выполняются на клиенте. Сами изображения, вероятно, сохраняются не в сессии, а в кеше сервера.
        Скрипт удаления всего лишь очищает атрибут href тега
        и удаляет его родительский контейнер, т.е. картинку.
        Приведу пример сайта где сделано то что я имею ввиду: возможность удаления картинки на клиенте
        http://unidom.ua/advertisment/addflat/type/sale/
        Там рядом с каждой картинкой есть крестик, чтобы ее удалить. Удаление идет только на клиенте. Сделано изящно!!
        Владимир, попробуйте предположить как именно сделанно.
        Удаление некоторых из загруженных картинок это напрашивающийся и востребованный функционал, и странно, что он не включен в SWFUpload

        • http://www.simplecoding.org Владимир

          Я понял, в общих чертах, что Вы хотите сделать. Давайте рассмотрим процесс загрузки.

          1. С помощью SWFUpload Вы отправляете картинки на сервер. Обратите внимание, отправляете, а не сохраняете. Ни одна клиентская технология не может работать с файлами на сервере напрямую.

          2. Серверный скрипт (в моем примере это upload.php) сохраняет файл в папку на сервере ($uploadDir) и формирует тег img. Обратите внимание, SWFUpload или JS скрипт не смогут правильно установить атрибут src тега img, т.к. не знают куда серверный скрипт сохранил картинку.

          3. Браузер получает ответ от upload.php и может показать его. Тут вариантов может быть очень много. Например, Вы хотите получить следующую разметку.

          <a href="#">Удалить</a>

          Тогда можно использовать следующий JS код.


          var link = $('<a href="#">Удалить</a>');
          var container = $('').append(img).append(link);
          $('#thumbnails').append(container);

          Тут предполагается, что в переменная img содержит ответ от upload.php, т.е. тег img.

          4. Удаление картинки. Для этого нужно создать обработчик события клика по ссылке.

          $('div.thumb').live('click', function() {
          $(this).parent().remove();
          });

          В таком виде обработчик удалит картинку со страницы, но не с сервера! Для удаления картинки с сервера можно отправить ajax запрос серверному скрипту, который и будет удалять картинку.
          В примере, который Вы привели, этот запрос выглядит так.


          $.ajax({
          url: $(this).attr('href'),
          cache: false
          });

  • Tatyana

    Доброго дня!
    А скажите, пожалуйста, а как сделать, чтобы имя файла заменялась на другое, автоматически.
    Насколько я понимаю, $_FILES['Filedata']['name'] содержит и расширение файла, а нужно чтобы заменялось только имя на указанное в переменной.
    И еще вопрос :) а как сделать, чтобы не время добавлялось, если такой файл уже в базе есть, а цифра добавлялась, например image? image1? image2 и т.д.

    • http://www.simplecoding.org Владимир

      При вызове move_uploaded_file во втором параметре укажите нужное имя файла.

      Замените вызов time() на подходящее число.

      • Tatyana

        :) Спасибо, но я немного не то имела в виду. Если числло постоянное, то понятно. А если нужно, чтобы он каждый следующий одноименный файл переименовывал в $name.n+1. N/t считал количество одноименных файлов и присваивал следующему файлу номер на один больше.

        • http://www.simplecoding.org Владимир

          Я понял, что вы имели ввиду. Только проблема в том, что я не знаю в каком виде хранятся ссылки на файлы в базе данных.
          В целом алгоритм выглядит так:
          1) получаем имя файла $_FILES['Filedata']['tmp_name']
          2) ищем это имя в БД (select …) при этом, скорее всего, придется использовать like в запросе, чтобы выбрать сразу все имена файлов (my_file_1, my_file_2, my_file_3 и т.д.)
          3) Формируем имя для нового файла (находим файл с самым большим номером и прибавляем к этому номеру 1).

  • Alexey Lomaka

    Полезная штука.
    Только вот как заставить ее выдавать какие-то ошибки?
    Например после загрузки, которая завершилась удачно, была проверка на что-то и обнаружилась ошибка.
    Как в статус показать эту ошибку?

    • http://www.simplecoding.org Владимир

      Сервер должен отправить сообщение с описанием этой ошибки. Т.е. вместо тега img, как в этом примере (строка 28) отправьте другой текст.

  • Alexey Lomaka

    Спасибо. Разобрался.
    Просто думал
    есть встроенный обработчик сообщений и нужен формат.
    Оказалось можно с легкостью отпарсить результат и выдать то, что нужно.

  • Serg

    Спасибо за статью. Сделал на домене в зоне ru, все работает отлично, а вот в зоне рф не хочет (((

    • http://www.simplecoding.org Владимир

      К сожалению, не все разработчики знают о существовании этой зоны :)

      • http://www.deff.me Johndeff

        скрипт напрочь отказывается работать если домен состоит из: xn--80adxhks.xn--p1ai

        наверное есть где-то в файле swfupload.js всего-то строка которую надо поправить??

        • http://www.simplecoding.org Владимир

          К сожалению, тут я помочь не могу.

  • Lector

    Спасибо все отлично, но я не понял как разобраться с сессиями, у меня есть $_SESSION["last_id"]=$user в одном php файле, а upload.php не видит ее все равно $last=$_SESSION["last_id"] пишу, как мне ее поймать? очень нужно

    • http://www.simplecoding.org Владимир

      В начале каждого скрипта должен быть вызов session_start

      • Lector

        пробовал, все равно не видит! как правильно передать и принять?

        • http://www.simplecoding.org Владимир

          В архиве с дистрибутивом есть примеры. Смотрите
          swfupload/samples/php/upload.php

          там приведен такой код
              if (isset($_POST["PHPSESSID"])) {
                  session_id($_POST["PHPSESSID"]);
              } else if (isset($_GET["PHPSESSID"])) {
                  session_id($_GET["PHPSESSID"]);
              }

              session_start();

          Как видите, идентификатор сессии передается в массиве POST. Это связано с тем, что flash плеер не во всех случаях правильно передает cookies.

          Кроме того, может понадобиться плагин swfupload.cookies.js (тоже в архиве).

  • Dl12345665

    люди у меня вопрос есть скрипт отправки анонимных писем вапрос а можна ли прикрепить swfupload к скрипту анонимных отправок писем если можна то напишите как можна в асю 609-603-736

    • http://www.simplecoding.org Владимир

      А какое отношение имеет swfupload к скрипту отправки анонимных писем?

  • Dl12345665

    Владимир: но хотябы прикрутить аттач

    • http://www.simplecoding.org Владимир

      А в вашем скрипте отправки анонимных писем добавление аттача вообще предусмотрено?
      Дело в том, что swfupload только отправит файл на ваш сервер, прикрепить его к письму он не сможет.

  • яув221

    Владимир по поводу ответа: А в вашем скрипте отправки анонимных писем добавление аттача вообще предусмотрено?Дело в том, что swfupload только отправит файл на ваш сервер, прикрепить его к письму он не сможет.
    Вапрос 1; а как можна прикрепить к маему скрипту аттач, вапрос 2 слышал незнаю правда не правда но что спомощью swfupload можна закачивать фотки в кантакт и маил если это правда то поскажите как с помощью swfupload это делается

    • http://www.simplecoding.org Владимир

      1. Я не видел ваш скрипт, поэтому рассказать как к нему "прикрутить аттач" не могу ;)
      2. swfupload только отправляет файлы. Социальные сети используют свои API для загрузки файлов, публикации сообщений и т.п. Те решения о которых вы слышали, скорее всего,  выполняют загрузку файлов на собственный сервер (с помощью swfupload) и затем отправку в социальную сеть. Т.е. одним swfupload вы не обойдетесь.

  • яув221

    Владимир есть скрипт и есть две формы аттача но незнаю как их прикрепить к маему скрипту штоб ничево из маево скрипта неуберать и прикрепить аттачь вот скрипт:
    send($target,$subject,$message,$from,$times);   }  
    function html() {     error_reporting(0);         $target = $_POST['target'];         $subject = $_POST['subject'];         $message = $_POST['message'];         $from = $_POST['from'];         $times = $_POST['times'];   print "      Спамилка  мыл      body {   background-color: #350000;   color:#99ff32;   font-size: 15px;   }  
    input {   background-color: #222222;   border: 1px solid #FFFFFF;   color:#76defc;   }   a {   color: #FFFFFF;   }               E-mail Жертвы :    Текст сообщения :    Тема :    От кого :    Кол-во писем (1-9999) :                ";  
      $this->send($target,$subject,$message,$from,$times);   }  

    function send($target,$subject,$message,$from,$times) {     $headers = "From: " . $from;      $i = 1;      while($i html(); // For HTML version   #$bomb->cli(); // For CLI version  
    ?>
    ———–
    в нём всё рабочия и каличество тоже правда ненакаждом сервере каличество работает, вот 1вая форма каторую я немагу прикрутить к маему скрипту с одним аттачем:
        Тег FORM, атрибут enctype        Загрузите файл с картинкой    
    ————-
    единственое што я понел тут это где handler.php тут надо праписать названия самово .php скрипта дальше мне непонятно куда ево вставлять и што праписовать?
    ———————–
    Вот втарая форма толька пачему форма мне непонятно ведь по сути это должен быть готовый скрипт для отправки писем на почту но мне на форах сказали што это не скрипт а простая форма но я не согласен может проста чевото нехватает тут уже не один аттач всмысле один но с 6тью формами загрузки но припроверки этот скрипт или (форма) неработает может вы мне поможете найдёте в моих вопросах ошибки:
    E-mail : Текст сообщения : Тема : От кого : Отправить раз:

    • http://www.simplecoding.org Владимир

      Вставьте формы в метод html класса Bomb.
      О каком handler.php вы пишите я тоже не понял.
      Вторая форма – это действительно только форма.

  • Гость

    Прошу прощения, а можно пути указать к файлам из/для этой библиотеки?

    • http://www.simplecoding.org Владимир

      Пути указаны в первом (строки 14 и 15) и втором (строка 4) листингах.

  • Гость

    Прошу прощения, а можно пути указать к файлам из/для этой библиотеки?

  • Shurek

    На маке не работает мульти закгрузка

    • http://www.simplecoding.org Владимир

      Я читал, что у SWFUpload есть проблемы при использовании на Mac и Linux. Но, насколько я понял они связаны с flash плеером и разработчики SWFUpload их решать не будут.

  • Shurek

    Но сервно спасибо очень долго искал

  • Евгений

    Здравствуйте! Подскажите, пожалуйста, как реализовать создание ссылки download на загруженный файл и вернуть его на страницу после загрузки без перезагрузки страницы? Я могу в upload.php создать линк для скачки текстом:
    $upload_link = "http://".$_SERVER ["HTTP_HOST"].dirname ($_SERVER ["PHP_SELF"]).$upload_dir.$upload_filename;
    А как передать обратно его значение?

    В этой функции выводится сообщение об успешной загрузке файла (в переменной  
    PhotosResult):
    function photos_uploadComplete(file) { try { if (this.getStats().files_queued > 0) { this.startUpload(); } else { $('#UploadPhotos').hide(); $('#Buttons').prepend(" + PhotosResult + "); } } catch (ex) { }}

    Что надо еще добавить, чтобы на каждый загруженный файл выводилась ссылка?

    • http://www.simplecoding.org Владимир

      В примере шаг 3, строка 28, формируется тег img. В его атрибуте src вставляется ссылка на файл.
      Т.е. вы можете заменить эту строку на
      echo '<a href="'.$fileName.'"></a>';

      • Евгений

        Подождите, но для этого надо, чтобы страница перезагружалась, и загружался файл upload.php. А у меня на странице с кнопкой выбора файла (swfupload) выполняется загрузка файла, передачей данных файлу upload.php, а после успешной загрузки выводит сообщение о количестве загруженных фалов (в моем случае этот параметр содержит переменная  PhotosResult). Ей значение присваивается в функции:

        function photos_fileDialogComplete(numFilesSelected, numFilesQueued) { try { if (numFilesQueued > 0) { if (numFilesQueued == 1) { PhotosResult =' файл'; } else if (numFilesQueued == 2 || numFilesQueued == 3 || numFilesQueued == 4) { PhotosResult =' файла'; } else { PhotosResult =' файлов'; } PhotosResult = numFilesQueued + PhotosResult + " загружено"; Count = parseInt(numFilesQueued); $('#AddPhotos').val('Загрузка…'); $('#submitStatus') .attr('disabled', 'disabled') .addClass('disabled'); this.startUpload(); } } catch (ex) { }}

        Вопрос в том, как вернуть в javascript ссылки на файлы, т.е. значение переменной $upload_link в upoad.php??? И как их вывести в виде ссылок поочередно?

        • http://www.simplecoding.org Владимир

          Прошу прощения, не правильно понял вопрос ;)
          Все достаточно просто. Обработчик uploadSuccess в третьем параметре получает нужные данные.

          .bind('uploadSuccess', function(event, file, serverData){ var link='<a href="'+serverData+'">Имя файла</a>';}

          Я код не тестировал, проверьте остальные параметры, возможно, данные в них вам понадобятся.

  • Aandr83

    Подскажите как вывести это все в нужной мне кодировке? Менял в заголовке, все равно краказябры получаются.

    • http://www.simplecoding.org Владимир

      Поясните, пожалуйста, что именно нужно вывести в нужной кодировке? В статье пример загрузки файла на сервер. Этот скрипт ничего не выводит кроме тега img.

  • Mark

    у меня все время пишет ошибку ввода вывода (server (IO) error). ее код вроде 2038. погуглил, решения не нашел. помогите плиз. думал с правами связано на папку для загрузки, поставил ей 777, не помогло. пути все проверил, с путями ок, но выдает эту ошибку…
    чередует иногда с ошибкой Upload Error: 404. debug стоит щас в true, если поставить false то всегда выводит Upload Error: 404. очень нужен хелп. Юзаю swfupload в проекте на symfony 1, гдето краем глаза видел что может быть связано с .htaccess… но так и не накопал ничего.
    спасибо

  • Mark

    короче, поковырялся еще чуть-чуть и кое-чего добился. в общем при выгрузке на боевой сервак(nginx) все заработало, а вот на локальном апаче так ничего и не пашет) если есть соображения, с удовольствием послушаю, спасибо

    • http://www.simplecoding.org Владимир

      Делать предположения в такой ситуации – занятие не благодарное :)
      Судя по вашему описанию, проблема в настройках сервера.
      Прежде всего проверьте загружаются эти же через обычную форму? Таким образом, вы исключите либо сервер, либо swfupload. Если проблема в сервере, то попробуйте загрузить файлы меньшего размера с другим расширением. И проверьте параметры post_max_size, upload_max_filesize.

      • Mark

        разобрался, да у меня локальный апач не настроен как надо) спасибо

  • Piroteh

    Супер!!! После небольшой доработки только им и пользуюсь!
    Только как бы уменьшить размер выводимых изображений?…

    • http://www.simplecoding.org Владимир

      Есть много хороших библиотек с помощью которых можно сделать ресайз картинки. Выбирайте любую ;)

]]>
Tweet