За последние 24 часа нас посетили 16412 программистов и 1678 роботов. Сейчас ищут 912 программистов ...

Загрузка и проверка изображения

Тема в разделе "JavaScript и AJAX", создана пользователем lucky64rus, 23 май 2012.

  1. lucky64rus

    lucky64rus Активный пользователь

    С нами с:
    16 апр 2012
    Сообщения:
    8
    Симпатии:
    0
    Цель: сделать форму для добавления статьи на сайт, с проверкой заполнения формы (в том числе и загрузки изображения) без перезагрузки страницы.
    Если все верно, то нужно загрузить изображение на сервер, а url данного изображения и значения полей формы занести в базу данных.
    Собственно форма:
    Код (Text):
    1.  
    2. <script type="text/javascript" src="jquery.js"></script>
    3. <script type="text/javascript" src="script.js"></script>
    4. <div id="add_news_container">
    5.     <form id="add_news_form" method="post" action="">
    6.         <label for="news_img">Загрузите картинку:</label>
    7.         <input type="file" name="news_img" id="news_img"/>
    8.         <br/>
    9.         <label for="title">Заголовок:</label>
    10.         <textarea name="title" id="title" cols="80%" rows="3"></textarea>
    11.  
    12.         <label for="description">Краткое описание:</label>
    13.         <textarea name="description" id="description" cols="80%" rows="5"></textarea>
    14.  
    15.         <label for="text">Текст:</label>
    16.         <textarea class="HTML" name="text" id="text" cols="80%" rows="20"></textarea>
    17.  
    18.         <input id="main_news" name="main_news" type="checkbox" value="1"/>&nbsp;<label for="main_news" id="main_news_label">Главная новость</label>
    19.         <br/>
    20.         <input type="submit" id="submit" value="Опубликовать" />
    21.         <input type="reset" id="reset" value="Сброс"/>
    22.     </form>
    23. </div>
    код скрипта "script.js":
    Код (Text):
    1. $(document).ready(function(){
    2.     /* Следующий код выполняется только после загрузки DOM */
    3.    
    4.     /* Данный флаг предотвращает отправку нескольких комментариев: */
    5.     var working = false;
    6.    
    7.     /* Ловим событие отправки формы: */
    8.     $('#add_news_form').submit(function(e){
    9.  
    10.         e.preventDefault();
    11.         if(working) return false;
    12.        
    13.         working = true;
    14.         $('#submit').val('Публикую...');
    15.         $('span.error').remove();
    16.        
    17.         /* Отправляем поля формы в submit.php: */
    18.         $.post('submit.php',$(this).serialize(),function(msg){
    19.  
    20.             working = false;
    21.             $('#submit').val('Опубликовать');
    22.            
    23.             if(msg.status){
    24.  
    25.                 /*
    26.                 /   Если вставка была успешной, добавляем комментарий
    27.                 /   ниже последнего на странице с эффектом slideDown
    28.                 /*/
    29.  
    30.                 $(msg.html).hide().insertBefore('#add_news_container').slideDown('10000');
    31.                 $('#body').val('');
    32.             }
    33.             else {
    34.  
    35.                 /*
    36.                 /   Если есть ошибки, проходим циклом по объекту
    37.                 /   msg.errors и выводим их на страницу
    38.                 /*/
    39.                
    40.                 $.each(msg.errors,function(k,v){
    41.                     $('label[for='+k+']').append('<span class="error">'+v+'</span>');
    42.                 });
    43.             }
    44.         },'json');
    45.  
    46.     });
    47.    
    48. });
    Файл submit.php:
    Код (Text):
    1. <?php
    2. // Сообщение об ошибке:
    3. error_reporting(E_ALL^E_NOTICE);
    4. /* Конфигурация базы данных */
    5. $db_host        = 'localhost';
    6. $db_user        = 'root';
    7. $db_pass        = '';
    8. $db_database        = 'article';
    9. /* Конец секции */
    10. $link = @mysql_connect($db_host,$db_user,$db_pass) or die('Не могу установить соединение с базой данных');
    11. mysql_query("SET NAMES 'utf8'");
    12. mysql_select_db($db_database,$link);
    13.  
    14. class news
    15. {
    16.     private $data = array();
    17.  
    18.     public function __construct($row)
    19.     {
    20.         $this->data = $row;
    21.     }
    22.    
    23.     public function markup()
    24.     {
    25.         /*
    26.         /   Данный метод выводит разметку XHTML для комментария
    27.         */
    28.        
    29.         return '
    30.             <div class="news">             
    31.                 <p>Новость «<strong>'.$this->data['title'].'</strong>» успешно опубликована.</p>
    32.             </div>
    33.         ';
    34.     }
    35.    
    36.     public static function validate(&$arr)
    37.     {
    38.         /*
    39.         /   Данный метод используется для проверки данных отправляемых через AJAX.
    40.         /
    41.         /   Он возвращает true/false в зависимости от правильности данных, и наполняет
    42.         /   массив $arr, который преается как параметр либо данными либо сообщением об ошибке.
    43.         */
    44.        
    45.         $errors = array();
    46.         $data   = array();
    47.        
    48.         if(!($data['title'] = filter_input(INPUT_POST,'title',FILTER_CALLBACK,array('options'=>'news::validate_text'))))
    49.         {
    50.             $errors['title'] = 'Введите заголовок.';
    51.         }
    52.        
    53.         if(!($data['description'] = filter_input(INPUT_POST,'description',FILTER_CALLBACK,array('options'=>'news::validate_text'))))
    54.         {
    55.             $errors['description'] = 'Введите краткое содержание новости.';
    56.         }
    57.        
    58.         if(!($data['text'] = filter_input(INPUT_POST,'text',FILTER_CALLBACK,array('options'=>'news::validate_text'))))
    59.         {
    60.             $errors['text'] = 'Введите текст новости.';
    61.         }
    62.        
    63.         $data['main_news'] = filter_input(INPUT_POST,'main_news');
    64.        
    65.         $data['news_img'] = filter_input(INPUT_POST,'news_img');
    66.        
    67.         if(!empty($errors)){
    68.            
    69.             // Если есть ошибки, копируем массив $errors в $arr:
    70.            
    71.             $arr = $errors;
    72.             return false;
    73.         }
    74.        
    75.         // Если данные введены правильно, подчищаем данные и копируем их в $arr:
    76.        
    77.         foreach($data as $k=>$v){
    78.             $arr[$k] = mysql_real_escape_string($v);
    79.         }
    80.         return true;
    81.        
    82.     }
    83.  
    84.     private static function validate_text($str)
    85.     {
    86.         /*
    87.         /   Данный метод используется как FILTER_CALLBACK
    88.         */
    89.        
    90.         if(mb_strlen($str,'utf8')<1)
    91.         return false;
    92.        
    93.         // Удаляем все оставщиеся символы новой строки
    94.         $str = str_replace(array(chr(10),chr(13)),'',$str);
    95.        
    96.         return $str;
    97.     }
    98.  
    99. }
    100.  
    101. /*
    102. /   Данный массив будет наполняться либо данными,
    103. /   которые передаются в скрипт,
    104. /   либо сообщениями об ошибке.
    105. /*/
    106.  
    107. $arr = array();
    108. $validates = news::validate($arr);
    109.  
    110. if($validates)
    111. {
    112.     /* Все в порядке, вставляем данные в базу: */
    113.     $date = date('Y-m-d');
    114.     $time = date('H:i');
    115.     mysql_query("   INSERT INTO news(title,description,date,time,text,main,img_url)
    116.                     VALUES (
    117.                         '".$arr['title']."',
    118.                         '".$arr['description']."',
    119.                         '".$date."',
    120.                         '".$time."',
    121.                         '".$arr['text']."',
    122.                         '".$arr['main_news']."',
    123.                         '".$arr['news_img']."'
    124.                     )");
    125.                    
    126.     $arr['id'] = mysql_insert_id();
    127.    
    128.     /*
    129.     /   Данные в $arr подготовлены для запроса mysql,
    130.     /   но нам нужно делать вывод на экран, поэтому
    131.     /   готовим все элементы в массиве:
    132.     /*/
    133.    
    134.     $arr = array_map('stripslashes',$arr);
    135.    
    136.     $insertedNews = new news($arr);
    137.  
    138.     /* Вывод разметки только-что вставленного комментария: */
    139.  
    140.     echo json_encode(array('status'=>1,'html'=>$insertedNews->markup()));
    141. }
    142. else
    143. {
    144.     /* Вывод сообщений об ошибке */
    145.     echo '{"status":0,"errors":'.json_encode($arr).'}';
    146. }
    147.  
    148. ?>
    С проверкой форм проблем не возникает, а вот как сделать так, чтобы изображение загружаемое пользователем проверялось "на лету"?
    (важен размер и то, чтобы оно являлось изображением, естественно)

    P.S. Код чужой, переделанный, поэтому вероятность ошибок 100%-ая. Советы по их исправлению приветствуются
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    на лету это как?
     
  3. lucky64rus

    lucky64rus Активный пользователь

    С нами с:
    16 апр 2012
    Сообщения:
    8
    Симпатии:
    0
    "На лету" - это без перезагрузки страницы.
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    в чем затык? аякс не работает? =)
     
  5. lucky64rus

    lucky64rus Активный пользователь

    С нами с:
    16 апр 2012
    Сообщения:
    8
    Симпатии:
    0
    Затык в том, что я не знаю как на аякс проверить изображение на тип и размер.
    Если все нормально - загрузить на сервер, если нет - сообщить об этом без перезагрузки страницы и без отправки формы
     
  6. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Аякс это просто способ сходить по урлу и получить ответ.
    Соотв. Вам надо закинуть файлик и как-то запросить его статус.
    Соотв. хорошо бы закидывая файлик присвоить ему идентификатор уникальный и по нему запрашивать результат.
     
  7. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Вообще, про загрузку файлов на сервер без перезагрузки страницы в интернете существует уже немало статей. И я помню, что сам уже пару раз отвечал на такой вопрос на этом форуме. Обычно делается это так - на странице создаётся невидимый iframe, а форме, через которую загружают файл - присваивается атрибут target="название_невидимого_фрейма". При нажатии на submit страница не перезагружается, а данные формы, включая файл - уходят на сервер. Ответ от сервера приходит в этот невидимый iframe. Сервер должен прислать в ответ некий JavaScript-код, который, загрузившись в тот невидимый iframe, сообщит пользователю о результате загрузке файла. Я обычно присылаю в ответ просто вызов какой-нибудь JS-функции родительского окна (по отношению к фрейму) и передаю ей параметры, в которых, собственно, результат загрузки файла - либо всё ок и файл загружен (тогда можно передать также id, присвоенный сервером загруженному файлу и ссылку на превью файла, чтобы JS-функция могла сразу вывести пользователю это превью и, например, ссылку на удаление), либо всё не ок и файл не загружен (тогда можно, например, также передать текст сообщения об ошибке).
    Ну а дальше, имея эти данные, ты уже можешь с помощью JavaScript вывести как угодно и куда угодно результат загрузки :)