Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 20.01.2020, 11:16
Новичок на форуме
Отправить личное сообщение для sdareios Посмотреть профиль Найти все сообщения от sdareios
 
Регистрация: 20.01.2020
Сообщений: 2

Форма загрузки изображения. Рефакторинг
Всем привет!

Пишу впервые на этом форуме. Так что простите, если что не так)

Написал HTML-форму, с помощью которой пользователь загружает свое фото (аву) на сайт. Сначала все это было на HTML + jQuery. Но меня в последнее время одолевает желание отказаться от jQuery в пользу нативного Javascript'а где это только возможно. Да, лучше позже, как говориться))

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

Сама форма
<div id="customer_photo" data-maxfilesize="{{ max_file_size }}">
  <img id="customer_photo_img" src="{{ photo }}" class="img-fluid">

  <form id="customer_photo_form">
    <input id="customer_photo_input" type="file" name="photo" accept="{{ mime_allowed }}" required>
  </form>

  <div id="customer_photo_callback"
    data-error_validation_by_type="{{ error_validation_by_type }}"
    data-error_validation_by_size="{{ error_validation_by_size }}">
  </div>
</div>

document.getElementById('customer_photo_input').addEventListener('change', changePhoto, false);

  function changePhoto(evt) {
    let file = evt.target.files[0];

    if (file.length !== 0) {
      if (!fileValidationByType(file)) {
        let message = document.getElementById('customer_photo_callback').getAttribute('data-error_validation_by_type');

        document.getElementById('customer_photo_callback').innerHTML = message;
      } else if (!fileValidationBySize(file)) {
        let message = document.getElementById('customer_photo_callback').getAttribute('data-error_validation_by_size');

        document.getElementById('customer_photo_callback').innerHTML = message;
      } else {
        fileUpload(file);
      }
    } else {
      console.log('Selected file is empty!');
    }
  }

  function fileValidationByType(file) {
    var fileTypes = [
      {% for mime in mime_allowed_array %}
        '{{ mime }}',
      {% endfor %}
    ]

    for (var i = 0; i < fileTypes.length; i++) {
      if (file.type === fileTypes[i]) {
        return true;
      }
    }

    return false;
  }

  function fileValidationBySize(file) {
    var maxfilesize = document.getElementById('customer_photo').getAttribute('data-maxfilesize');

    if (file.size <= maxfilesize) {
      return true;
    }

    return false;
  }

  function fileUpload(file) {
    var url  = '{{ url }}',
        data = new FormData();

    data.append('photo', file);

    var xhr = new XMLHttpRequest();

    xhr.onload = function() {
      if (xhr.readyState === xhr.DONE) {
        if (xhr.status === 200) {
          try {
            var data = JSON.parse(xhr.responseText);
          } catch (e) {
            // console.log(e.message + " in " + xhr.responseText);
            return;
          }

          fileUploadCallback(file, data);
        }
      }
    };

    xhr.open('POST', url, true);
    xhr.send(data);
  }

  function fileUploadCallback(file, data) {
    if (data.error) {
      // responseText
      document.getElementById('customer_photo_callback').innerHTML = data.error;
    } else if (data.success) {
      // responseText
      document.getElementById('customer_photo_callback').innerHTML = data.success;

      // replacePhoto
      var img = document.createElement('img');
      img.id = 'customer_photo_img';
      img.className = 'img-fluid';
      img.src = window.URL.createObjectURL(file);

      document.getElementById('customer_photo_img').replaceWith(img);
    }
  }


P.S. Надеюсь, все здесь понятно. Старался писать аккуратно)
Ответить с цитированием
  #2 (permalink)  
Старый 20.01.2020, 16:04
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от sdareios
{% for mime in mime_allowed_array %}
        '{{ mime }}',
      {% endfor %}
как разу и должно быть вот здесь accept="{{ mime_allowed }}", и проверятся рег. выражением. А

Сообщение от sdareios
var url  = '{{ url }}',
вот тут <form action="{{ url }}".

Вообще, старайтесь, без большой на то надобности, не трогать JS вставками сервера.
Ответить с цитированием
  #3 (permalink)  
Старый 20.01.2020, 16:51
Новичок на форуме
Отправить личное сообщение для sdareios Посмотреть профиль Найти все сообщения от sdareios
 
Регистрация: 20.01.2020
Сообщений: 2

Сообщение от laimas Посмотреть сообщение
как разу и должно быть вот здесь accept="{{ mime_allowed }}", и проверятся рег. выражением.
Оно то да, вот только пользователь все равно сможет загрузить файл другого типа выбрав его в окне выбора файла



Поэтому я и добавил проверку по типу файла

Последний раз редактировалось sdareios, 20.01.2020 в 16:53.
Ответить с цитированием
  #4 (permalink)  
Старый 20.01.2020, 17:31
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от sdareios
вот только пользователь все равно сможет загрузить файл другого типа выбрав его в окне выбора файла
Это как? Значения accept не все браузеры в общем то слушаются так как вам хочется, но тип файла file.type будет определен (есть небольшие косяки с мелкософтовскими документами, как выяснилось, но вам это боком). А указанные типы в accept как image/jpeg,image/png... легко превратить в шаблон рег. выражения и создав по нему RegExp. Проверка file.type по этому шаблону никак не даст загрузить с диска не тот тип.

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


Вы мусортите в js коде вставками php, если потребуется подключение js, то это уже работать не будет.

PS. Значение accept можно превратить и в массив, искать в нем вхождение file.type (indexOf(), includes()).

Последний раз редактировалось laimas, 20.01.2020 в 17:39.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Форма для загрузки файла по ссылке kupidon Общие вопросы Javascript 64 18.02.2018 18:23
Прогресс загрузки большого изображения или файла - как сделать Почемучкин Events/DOM/Window 7 19.10.2012 21:03
Ожидание загрузки изображения oleg_pantyukhin AJAX и COMET 4 15.10.2012 20:33
Loader на время загрузки изображения shilinpavel Javascript под браузер 2 26.05.2012 09:32
Помогите пожалуйста с обьяснением загрузки изображения на сервер. 0931454574 Серверные языки и технологии 3 11.05.2011 18:05