Перейти к содержимому

Фотография
- - - - -

Загрузка изображения на сервер через форму


  • Вы не можете создать новую тему
  • Закрытая тема Тема закрыта
Сообщений в теме: 9

#1 VladimirBuzin

VladimirBuzin

    Прохожий

    Топикстартер
  • Участник
  • 0
    19 сообщ.

Отправлено 31 Август 2018 в 16:34

Добрый день! Я пишу сайт для стоматологического кабинета, и у меня возникли проблемы с загрузкой изображений. Все имена полей формы и индексы массива POST прописаны верно, но почему-то сервер "жалуется" на неверно названный индекс image. Данные передавал напрямую, без всяких AJAX, но почему изображение не считалось?

 

doctor_insert.php

<?PHP
include_once 'connect_pdo.php';
$statement = $connection->query('SELECT * FROM speciality');
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Добавление нового врача</title>
  <link rel="shortcut icon" href="images/toothdoctor_diente_10728.ico" type="image/x-icon">
  <link rel="stylesheet" href="css/style_2.css">
  <link rel="stylesheet" href="css/window-style.css" type="text/css" media="all">
  <script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
</head>
<body>
<div class="page-wrapper">
  <form class="sign-up" action="insert_doctor.php" method="POST" id="doctor_insert" enctype=”multipart/form-data”>
    <h1 class="sign-up-title">Добавление нового врача</h1>
    <input type="text" name="surname" size="30" class="sign-up-input" pattern="[А-Яа-яЁё]{2,30}" placeholder="Фамилия" title="Введите фамилию на русском языке, от 2 до 30 букв без пробелов" maxlength="30" required>
    <input type="text" name="name" size="30" class="sign-up-input" pattern="[А-Яа-яЁё]{2,30}" placeholder="Имя" title="Введите имя на русском языке, от 2 до 30 букв без пробелов" maxlength="30" required>
    <input type="text" name="patronymic" size="30" class="sign-up-input" pattern="[А-Яа-яЁё]{7,30}" placeholder="Отчество" title="Введите отчество на русском языке, от 7 до 30 букв без пробелов" maxlength="30" required>
    Добавить фотографию:<br />
    <input type="file" name="image" class="sign-up-input" required><br />
    <select name="med_spec" class="sign-up-input" required>
    <option>Выберите область медицины</option>
    <?PHP
    while($row = $statement->fetch(PDO::FETCH_ASSOC)) {
    echo '<option value="'.$row["spec_id"].'">'.$row["medspec"].'</option>';
    }
    echo '</select>';
    ?>
    <input type="submit" value="Добавить" class="sign-up-button">
  </form>
 
  <div class="about">
    <p class="about-links">
      <a href="#" onclick="history.back();return false;">Назад</a>
    </p>
    <p class="about-author">
      &copy;2018 Corporation Buzin-Tech by VovaBuzin &bull;
    </p>
  </div>
</div>
<div class="modal-wrapper">
 
  <div class="modal">
 
    <div class="head">
 
      <a class="btn-close trigger" href="#">
 
        <i class="fa fa-times" aria-hidden="true"></i>
 
      </a>
 
    </div>
 
    <div class="content">
 
        <div class="good-job">
 
          <i class="fa fa-thumbs-o-up" aria-hidden="true"></i>
 
          <h1></h1>
 
        </div>
 
    </div>
 
  </div>
 
</div>
</body>
</html>

insert_doctor.php

<?php
include_once 'connect_pdo.php';
if (!empty($_POST)) {
$familija=$_POST['surname'];
$familija = str_replace(' ', '', $familija);
$imja=$_POST['name'];
$imja = str_replace(' ' ,'', $imja);
$otchestvo=$_POST['patronymic'];
$otchestvo = str_replace(' ' ,'', $otchestvo);
$image=$_FILES['image']['name'];
$image = str_replace(' ', '', $image);
$medspec_id = @intval($_POST['med_spec']);
if((isset($_FILES)) && ($_FILES['image']['error'] == 0) && (($_FILES['image']['type'] == 'image/gif') || ($_FILES['image']['type'] == 'image/jpeg') || ($_FILES['image']['type'] == 'image/png'))){
if (move_uploaded_file($_FILES['image']['tmp_name'], $_SERVER['DOCUMENT_ROOT'].'/images/'.$_FILES['image']['name'])) {
$statement = $connection->query('SELECT COUNT(*) FROM doctor');
$new_doctor_id = $statement->fetchColumn() + 1;
$statement = $connection->prepare("INSERT INTO doctor VALUES (:docnum, :lastname, :firstname, :otchestvo, :photo, :med_spec)");
$statement->bindParam(':docnum', $new_doctor_id);
$statement->bindParam(':lastname', $familija);
$statement->bindParam(':firstname', $imja);
$statement->bindParam(':otchestvo', $otchestvo);
$statement->bindParam(':photo', $image);
$statement->bindParam(':med_spec', $medspec_id);
$statement->execute();
echo "Новый врач добавлен!<br />Файл корректен и был успешно загружен!";
} else {
echo "Возможная атака с помощью файловой загрузки!";
}
} else {
echo 'Ошибка передачи изображения';
}
} else {
echo 'Данные не получены!';
}
?>

При попытке загрузить изображение сервер выдал ошибки:
 

Notice: Undefined index: image in C:\xampp\htdocs\stomkab\insert_doctor.php on line 10

Notice: Undefined index: image in C:\xampp\htdocs\stomkab\insert_doctor.php on line 13

Notice: Undefined index: image in C:\xampp\htdocs\stomkab\insert_doctor.php on line 13

 


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

; Whether to allow HTTP file uploads.
; http://php.net/file-uploads
file_uploads=On
 
; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
; http://php.net/upload-tmp-dir
upload_tmp_dir="\xampp\tmp"
 
; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize=2M

Если ошибка в файле с формой, то в чём там дело? Про enctype я не забыл. Дело здесь случайно не в multiple? Или папку с сайтом нужно помещать не напрямую в htdocks, а в папку, лежащую в этой категории (как матрёшка)? Или могут быть у главной папки XAMPP какие-то ограничения по загрузке, созданию, чтению и записи файлов? Извините, но сайт на локалхосте, а собственного домена у меня нет. Так что придётся разворачивать архивы во вложениях.

Прикрепленные файлы

  • Прикрепленный файл  sql.zip   4,95К   28 Количество загрузок:
  • Прикрепленный файл  stomkab.zip   4,09МБ   4 Количество загрузок:

  • 0

Спонсор

#2 BaNru

BaNru

    Пацифизжу

  • суперМодератор
  • 1016
    3 712 сообщ.

Отправлено 31 Август 2018 в 18:27

Перед строкой

$image=$_FILES['image']['name'];

Сделай вывод на экран того, что приходит в массиве:

print_r($_FILES['image']);

А ещё: присвоение переменной из десятой строки ($image=$_FILES['image']['name'];)

надо делать после проверки $_FILES, то есть внутри условия

if((isset($_FILES)) && ($_FILES['image']['error'] == 0) && (($_FILES['image']['type'] == 'image/gif') || ($_FILES['image']['type'] == 'image/jpeg') || ($_FILES['image']['type'] == 'image/png'))){

  • 0

#3 VladimirBuzin

VladimirBuzin

    Прохожий

    Топикстартер
  • Участник
  • 0
    19 сообщ.

Отправлено 31 Август 2018 в 20:47

Странно, но массив POST полностью вывелся, а массив FILES оказался абсолютно пустым. Хотя я пытался передать изображение напрямую, не используя JAVAscript, сервер его не распознал. Всё ли в порядке с текстом моего файла php.ini, касающимся загрузки файлов на сервер? Как узнать ограничения папки на загрузку файлов? Почему вдруг поле image у меня оказалось в посте, а не в массиве FILES? Как загрузить изображение на сервер через форму в обход этого "корявого" суперглобального массива? Не все люди должны лазить в корень сайта и подсовывать туда картинки напрямую. Есть ли другой алгоритм загрузки файлов без применения массива FILES? Как поле image сделать принадлежащим массиву FILES, а не POST? В блогах написано, что обязательным атрибутом в формах для загрузки файлов должен быть enctype, А О ЧЁМ ЕЩЁ МЫ ЗАБЫЛИ?


Ой Господи, как обидно, что мы оба лоханулись, и кавычки над enctype проглядели. Они кириллические, а не латинические.


  • 0

#4 BaNru

BaNru

    Пацифизжу

  • суперМодератор
  • 1016
    3 712 сообщ.

Отправлено 31 Август 2018 в 21:01

Почти на все вопросы есть ответы в мануале
http://php.net/manua...post-method.php
Попробуйте сделать всё по инструкции от туда.
 
PS Не забудьте, что проверки расширения файла - не достаточно для проверки файла.
Этого может быть достаточно, если загружать будут проверенные люди.
Если же форма общедоступна, то хакеры могут попытаться вам залить шел на сайт.
И тут уже всё будет зависеть от верной настройки хостинга.
 
PSS В вашем коде потенциально много не очень хороших мест
Например
1)

$familija = str_replace(' ', '', $familija);

Это неверно. А если будет фамилия Панкратов Черный, именно через пробел?
Для обрезки крайних пустых символов есть функция trim(), она удобнее и правильнее.
 
2)
Все поступающие данные надо как минимум обрабатывать через htmlspecialchars()
 
3)
По хорошему наличие всех элементов POST тоже лучше проверять, как это сделано с картинками

if(isset($_POST['surname']) && isset($_POST['patronymic'])){}
else{echo 'форма заполнена не полностью';}

4)
Небольшой совет: некоторые строки можно писать в одну строчку, это удобнее. Вместо

$otchestvo=$_POST['patronymic'];
$otchestvo = str_replace(' ' ,'', $otchestvo);

написать

$otchestvo = str_replace(' ' ,'', $_POST['patronymic']);

А ещё правильнее, как я выше сказал - через trim()

$otchestvo = trim( $_POST['patronymic'] );

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

$otchestvo = trim( $_POST['patronymic'] );
if(empty($otchestvo)){echo 'Отчество введено неверно!';}

empty()
Точнее даже так, это минимально допустимая защита

$otchestvo = trim( htmlspecialchars( $_POST['patronymic'] ) );
if(empty($otchestvo)){echo 'Отчество введено неверно!';}

  • 0

#5 miketomlin

miketomlin

    Частый гость

  • Участник
  • 17
    73 сообщ.

Отправлено 31 Август 2018 в 21:07

Странные кавычки у значения enctype.


  • 1

#6 VladimirBuzin

VladimirBuzin

    Прохожий

    Топикстартер
  • Участник
  • 0
    19 сообщ.

Отправлено 31 Август 2018 в 21:26

У меня есть проверка на пустоту массива POST:

if(!empty($_POST)) {
// работаем дальше
} else {
  echo 'Данные не получены!';
}

Также я навесил полям паттерны и атрибут required:

    <input type="text" name="surname" size="30" class="sign-up-input" pattern="[А-Яа-яЁё]{2,30}" placeholder="Фамилия" title="Введите фамилию на русском языке, от 2 до 30 букв без пробелов" maxlength="30" required>
    <input type="text" name="name" size="30" class="sign-up-input" pattern="[А-Яа-яЁё]{2,30}" placeholder="Имя" title="Введите имя на русском языке, от 2 до 30 букв без пробелов" maxlength="30" required>
    <input type="text" name="patronymic" size="30" class="sign-up-input" pattern="[А-Яа-яЁё]{7,30}" placeholder="Отчество" title="Введите отчество на русском языке, от 7 до 30 букв без пробелов" maxlength="30" required>
    Добавить фотографию:<br />
    <input type="file" name="image" class="sign-up-input" required><br />

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


  • 0

#7 BaNru

BaNru

    Пацифизжу

  • суперМодератор
  • 1016
    3 712 сообщ.

Отправлено 31 Август 2018 в 22:08


У меня есть проверка на пустоту массива POST:

Это проверяет весь массив POST, а я говорю про отдельные элементы

 


Также я навесил полям паттерны и атрибут required:

Эти паттерны ничего не значат в старых браузерах (а может быть и в некоторых новых мобильных) и при обходе ботами/скриптами.

А в новых браузерах, где они работают - они не учитывают Тире и Пробел. Фамилии бывают двойные.

 


Странные кавычки у значения enctype.

Чёрт! Как ты это сделал!? Как ты это увидел?! VladimirBuzin, действительно правьте кавычки (может где-то ещё есть) и проверяйте свой скрипт снова.


  • 0

#8 VladimirBuzin

VladimirBuzin

    Прохожий

    Топикстартер
  • Участник
  • 0
    19 сообщ.

Отправлено 31 Август 2018 в 22:19

 

 

Ой Господи, как обидно, что мы оба лоханулись, и кавычки над enctype проглядели. Они кириллические, а не латинические.

 

Кавычки я увидел и без подсказок, потому что если поле с изображением осталось постом, а не стало файлом, то, скорее всего,  дело в enctype. Я внимательно его просмотрел и отметил этот момент постом выше перед указанием уязвимостей, а за ошибки спасибо!


  • 0

#9 BaNru

BaNru

    Пацифизжу

  • суперМодератор
  • 1016
    3 712 сообщ.

Отправлено 31 Август 2018 в 22:55

Когда отвечал - в сообщение этого ещё не было :)

 

Я не понял: заработало или нет?

Если нет, то пробуйте по мануалу, а дальше, если не получится, будем смотреть.


  • 0

#10 VladimirBuzin

VladimirBuzin

    Прохожий

    Топикстартер
  • Участник
  • 0
    19 сообщ.

Отправлено 01 Сентябрь 2018 в 00:25

Всё сработало! Спасибо! Надо же было создать большую шумиху из-за такой мелочи с кавычками!? Вывел оба массива и заметил ошибку только тогда, когда поле с нужным мне индексом оказалось в посте, а не в файле. И сразу понял, почему так произошло.


  • 0



Похожие темы Свернуть

Статистика

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 скрытых пользователей