Мультизагрузка файлов [решение]

  • 3 Ответов
  • 163 Просмотров

0 Пользователей и 1 Гость просматривают эту тему.

*

Liss

  • Давно я тут
  • ****
  • 218
  • 9
Joomla 3.7.2
RSForm 1.52.12

Внимание: два важных факта, которые надо принять (или не принять)
1. доработка исходного кода компонента (со всеми вытекающими проблемами с дальнейшим его обновлением)
2. расскажу только про непосредственно загрузку файлов. Вопрос записи в БД остается в ваших руках

Грузить будем красиво, нам поможет проект https://www.fyneworks.com/jquery/multifile/
Скачиваем jquery.MultiFile.js и кидаем его в /media/com_rsform/js

Править исходный код нужно будет всего в двух файлах:
/administrator/components/com_rsform/helpers/rsform.php
/administrator/components/com_rsform/helpers/fields/fileupload.php

Немного теории. У нас на форме может быть любое кол-во полей типа type="file". Это означает, что в обработчике мы принимаем двухуровневый массив из данных: первый уровень - это массив полей, второй уровень - это массив с информацией о файле ($file['name'], $file['error'] и т.д., погуглите общую теорию о передачи файлов через post). Если мы хотим мульзагрузку, то обработчик принимает уже трехуровневый массив:
 
Код
 поле 1
   - файл 1
     - имя файла
     - код ошибки
     - временная папка
     - размер
  - файл 2
    - имя
    - и т.д
 поле 2
   - файл 1
     - и т.д
   - файл 2

и т.д.
 

*

Liss

  • Давно я тут
  • ****
  • 218
  • 9
Re: Мультизагрузка файлов [решение]
« Ответ #1 : 08.06.2017, 15:31:16 »
строки пишу примерно, из-за доработок нумерация у меня скорее всего "поехала"

итак файл fileupload.php, допилим функцию function getFormInput()
строка 48
это
Код
$html .= ' name="'.$this->escape($name).'"'.
меняем на это
Код
$html .= ' name="'.$this->escape($name).'[]"'.
Таким образом мы определяем массив (а не одну переменную, как изначально)

в районе строки 58 перед return $html; вставляем
Код
RSFormProAssets::addScript(JHtml::script('com_rsform/jquery.MultiFile.js', false, true, true));
Таким образом подключаем нашу "красоту"

теперь допилим function processBeforeStore($submissionId, &$post, &$files)
ее содержание должно быть таково:
Код: php-brief
foreach ($files[$this->name] as $file) {
  if ($file) {
   
      if (!empty($file['name']) && $file['error'] == 0) {
     
        $prefixProperty = $this->getProperty('PREFIX', '');
$destination    = $this->getProperty('DESTINATION', '');
// Prefix
$prefix = uniqid(''). '-';
if (strlen(trim($prefixProperty)) > 0) {
  $prefix = RSFormProHelper::isCode($prefixProperty);
}

// Path
$realpath = realpath($destination . DIRECTORY_SEPARATOR);
  if (substr($realpath, -1)!= DIRECTORY_SEPARATOR) {
    $realpath .= DIRECTORY_SEPARATOR;
  }

        // Filename
$fi = $realpath . $prefix . $file['name'];
        if (JFile::upload($file['tmp_name'], $fi, false, (bool) RSFormProHelper::getConfig('allow_unsafe'))){

          // Tut kod zapisi v BD. Originalniy kod tut ne rabotaet

        }
      }
   
  }
}

Про запись в БД: изначально компонент может грузить только один файл, и в БД он пишется вот так:
---
SubmissionValueId            | FormId    | SubmissionId   | FieldName | FieldValue
уникальный номер записи | ID формы | ID заполнения | имя поля   | значение поля (вот тут будет имя файла)
---
но у нас теперь не имя файла, а целый массив из имен. Хотите, пишите туда массив (сериализовать не забудьте). Хотите, пишите сюда некий ID, а сами файлы в отдельную таблицу, и группа файлов от туда будет цепляться по этому некому ID. В любом случае далее необходимо уже переписывать код вывода результатов
« Последнее редактирование: 08.06.2017, 15:36:57 от Liss »

*

Liss

  • Давно я тут
  • ****
  • 218
  • 9
Re: Мультизагрузка файлов [решение]
« Ответ #2 : 08.06.2017, 16:02:28 »
файл RSForm.php
строка в районе 2460, нас интересует секция, которая в оригинале прокомменитирована вот так
// Upload field
В этой секции происходит валидация формы (проверка расширения, размера - это все настраивается в админке при создании поля). Концепция правки кода тут аналогична по смыслу и объясняется тем же: у нас массив теперь трехуровневый. Выглядит код теперь так (это НЕ сразу после // Upload field, а ниже, смотрите и сравнивайте с оригинальным кодом) :
Код: php-brief

  if ($files = JFactory::getApplication()->input->files->get('form', null, 'raw')) {
    foreach ($files as $file) {
      foreach ($file as $fil) {  
        $name = $fil['name'];
        $tmp_name = $fil['tmp_name'];
        $error = $fil['error'];
        $size         = $fil['size'];

        // File has not been sent but it's required
if ($error == UPLOAD_ERR_NO_FILE && $required && !$originalUpload) {
  $invalid[] = $data['componentId'];
  continue;
}

        // File has been uploaded correctly to the server
if ($error == UPLOAD_ERR_OK) {
  // Let's check if the extension is allowed
  $extParts = explode('.', $name);
  $ext = strtolower(end($extParts));
  $acceptedExts         = !empty($data['ACCEPTEDFILES'])? self::explode($data['ACCEPTEDFILES']) : false;

  // Let's check only if accepted extensions are set
  if ($acceptedExts) {
    $accepted = false;
    $extListForMsg ='';
            foreach ($acceptedExts as $acceptedExt) {
      $acceptedExt = trim(strtolower($acceptedExt));
      $extListForMsg .= $acceptedExt.', ';
      if (strlen($acceptedExt) && $acceptedExt == $ext) {
        $accepted = true;
break;
      }
    }
    if (!$accepted) {
      $invalid[] = $data['componentId'];
      $extListForMsg = substr($extListForMsg, 0, -2);
      $msg = $name.' – '.JText::_('RSFP_UPLOAD_ERR_EXT').' '.$extListForMsg;
    }
  }

  // Let's check if it's the correct size
  if ($size > 0 && $data['FILESIZE'] > 0 && $size > $data['FILESIZE']*1024) {
    $invalid[] = $data['componentId'];
    $msg = $name.' – '.JText::_('RSFP_UPLOAD_ERR_FORM_SIZE');
    continue;
  }
  if (isset($msg)) {
    JFactory::getApplication()->enqueueMessage($msg, 'warning');
  }
        }
        elseif ($error != UPLOAD_ERR_NO_FILE) {
// tut kod ostavlyaem kak est', nichego ne menyaem
        }
      }
    }
  }
тут я также ввел языковую переменную RSFP_UPLOAD_ERR_EXT, которую необходимо прописать в языковой файл /language/ru-RU/ru-RU.com_rsform.ini
RSFP_UPLOAD_ERR_EXT="формат файла не разрешён в настройках этой формы. Допустимы следующие форматы файлов: "

*

Liss

  • Давно я тут
  • ****
  • 218
  • 9
Re: Мультизагрузка файлов [решение]
« Ответ #3 : 08.06.2017, 16:11:01 »
чтобы подключенный jquery.MultiFile.js отрабатывал наше поле, в админке в настройках поля во вкладке "атрибуты" в поле "доп. атрибуты" пишем
Код
class="multi"
если хотите, чтоб показывались превьюшки загружаемых файлов пишем так
Код
class="multi with-preview"


если хотите, чтоб файлы цеплялись не по одному, а сразу группой (т.е. через "обзор" можно выделить несколько файлов разом), пишем так
Код
class="multi with-preview" multiple

Вообще посмотрите сайт проекта этого плагина, там много настроек и примеров

PS не забывайте, что помимо ограничения на размер загружаемого файла (каждого), есть ограничение на размер всей формы целиком. По умолчанию, это 20 Mb (изменяется в php.ini)
PPS и еще про запись в БД: специфика моей задачи скорее подразумевает запись информации о загружаемых файлах в отдельную таблицу. Если интересно продолжение, напишу (ну как доделаю)

Всем добра