Drupal → Загрузка файлов средствами Form API

24.04.2011

Пример загрузки картинки с помощью Form API:

/**
 * Form builder.
 */
function mymodule_myform() {
  $form['file'] = array(
    '#type' => 'file',
    '#title' => 'Картинка',
    '#description' => 'Выберите файл с расширением jpg, jpeg, png или gif',
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Отправить',
  );

  return $form;
}

/**
 * Form validate callback.
 */
function mymodule_myform_validate($form, &$form_state) {
  $validators = array(
    'file_validate_is_image' => array(), // Проверка, действительно ли файл является изображением
    'file_validate_extensions' => array('png gif jpg jpeg'), // Проверка на расширения
    'file_validate_size' => array(1 * 1024 * 1024), // Проверка на размер файла (максимум 1mb)
  );
  // Загружаем файл в sites/default/files (по умолчанию)
  if ($file = file_save_upload('file', $validators, 'public://')) {
    $form_state['values']['file'] = $file; // передаём информацию о файле в ф-ю mymodule_form_submit()
  }
  else {
    form_set_error('file', 'Файл не был загружен');
  }
}

/**
 * Form submit callback.
 */
function mymodule_myform_submit($form, &$form_state) {
  $file = $form_state['values']['file'];
  $file->status = FILE_STATUS_PERMANENT; // Изменяем статус файла на "Постоянный"
  file_save($file); // Сохраняем новый статус
  drupal_set_message('Картинка загружена');
}

Важно помнить, что ф-я file_save_upload() загружает файл на сервер, добавляет информацию о нём в таблицу file_managed и помечает его как "Временный", поэтому если вам необходимо пользоваться файлом в дальнейшем, то нужно в submit-е формы изменять статус файла на "Постоянный" (FILE_STATUS_PERMANENT) и вызывать file_save(), чтобы файл автоматически не удалился по прошествии времени .

Полезное дополнение к статье — Использование виджета AJAX загрузки файлов в своих формах.

Написанное актуально для
Drupal 7
Похожие записи

Комментарии

Vydrin_AP
16.05.2011, 11:53

Добрый день!
file_save_upload(), как и move_uploaded_file() некорректно загружают файлы с русскими именами, нашел вот это решение, из него два вопроса:
1. Это правильное решение или у вас свой взгляд на решение этой проблемы?
2. Если все же правильное, то в какой из .htaccess вносить изменения? Их у меня два (в корне сайта и в sites\default\files)?

Второй день бьюсь. Помогите пожалуйста!

PS: пробовал вносить во все свои .htaccess, ничего не помогает.

Vydrin_AP
16.05.2011, 14:35

Пока ждал ответа докопался, что проблема не в этом. Нужно было сохранять файл из GET запроса, сохранялся криво, пока не попробовал iconv().
Спасибо )

Михаил
20.06.2011, 16:37

Если у меня несколько полей для загрузки файлов вида:

$form['file'][0] = array(
    '#type' => 'file',
  );

$form['file'][1] = array(
    '#type' => 'file',
  );

...

Как в этом случае будет выглядеть сохранение файлов?
В частности, интересует вид первого параметра в file_save_upload()

Михаил
20.06.2011, 17:04

А если индексы тройные?

$form['attachment'][$i]['file'] = array(
     '#type' => 'file',
);
Михаил
21.06.2011, 12:05

А вы сами пробовали так сделать? У меня не работает ни с двойными, ни с тройными индексами.

Я просто оставлю это здесь:
file_validate_extensions() Check that the filename ends with an allowed extension. This check is not enforced for the user #1.

Гость
19.12.2011, 14:54

Создал страницу, на странице добавил форму на форме:

$form = array(
    '#attributes' => array('enctype' => 'multipart/form-data'),
  );
  
  $form['upload'] = array(
    '#type' => 'file',
    '#description' => t('Upload only .xls files'),
  );
  
  $form['submit'] = array(
    '#type'  => 'submit', 
    '#value' => t('Import'),
  );
  
  return $form;

Вот функция валидации:

if (isset($form['upload'])) {
    $validators = array(
      'file_validate_extensions' => array('xls'),
    );
    $dir = 'public://';
    $file = file_save_upload('upload', $validators, $dir);
    if ($file) {
      $form_state['values']['upload'] = $file;
    }
    else {
      form_set_error('upload', t('Error. File is not .xls'));
    }
  }

На сабмите:

$file = $form_state['values']['upload'];
$file->status = FILE_STATUS_PERMANENT;
file_save($file);

Нужно мне загружать файлы екселя и с нами уже работать. Выбивает ошибка вот на этой строчке $file = file_save_upload('upload', $validators, $dir);

Ошибка:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'public://import_1.xls' for key 'uri': INSERT INTO {file_managed} (uid, filename, uri, filemime, filesize, status, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6); Array ( [:db_insert_placeholder_0] => 1 [:db_insert_placeholder_1] => import.xls [:db_insert_placeholder_2] => public://import_1.xls [:db_insert_placeholder_3] => application/vnd.ms-excel [:db_insert_placeholder_4] => 28160 [:db_insert_placeholder_5] => 0 [:db_insert_placeholder_6] => 1324291479 ) в функции drupal_write_record()

Что не так я написал? Спасибо.

Гость
09.01.2012, 20:35

вставил скрипт в, но у меня выдает ошибку. В чем может быть проблема?
Call to undefined function file_save() in C:\xampp\htdocs\dp\sites\all\modules\object\object.inc on line 211

Гость
09.01.2012, 20:40

понятно, а как можно реализовать загрузку файлов в 6 версии?

Гость
09.01.2012, 20:59

Спасибо, но,у меня еще вопросы:

 $dest_path = 'upload_directory/file';
    $result = file_copy($file, $dest_path, FILE_EXISTS_RENAME);

upload_directory/file Эту директорию надо где то создавать?

я создаю при установке/включении своего модуля в hook_install/hook_enable:

  $path = file_create_path(file_directory_path() .'/upload/dir1');
  file_check_directory($path, FILE_CREATE_DIRECTORY); 

это путь к файлу. если директории нет, то её естественно нужно создать и дать соответствующие права

Гость
09.01.2012, 21:21

Спасибо, скрипт написал -он копирует файл в папку files, но у меня еще 1 вопрос: что бы
получить ссылку на скачивание файла (для занесения её в бд), в хуке в submit, в функцию file_create_url какой параметр можно передать?

путь к файлу относительно папки drupal

Гость
09.01.2012, 21:37

а как можно получить путь к файлу? Можно ли как то использовать объект $file, который только загрузили?

Гость
30.03.2012, 20:43

А как реализовать, что бы в - drupal_set_message('Картинка загружена') - выводилось еще
и название загруженной картинки?

А можно ли как-то аналогично с помощью Form API реализовать мульти-загрузку нескольких файлов? Просто в этом примере стандартный элемент формы типа file берёт только один файл за раз. Пытался по-всякому дописывать к полю атрибут multiple, но что-то безрезультатно. И не очень понятно, что в этом случае передовать первым аргументом в функцию file_save_upload.

Потом попробовал вместо '#type' => 'file' вставить загрузчик plupload ('#type' => 'plupload'), но тут опять-таки непонятно, как передать то, что он подгружает, в file_save_upload

function staff_form_submit($form, &$form_state) {
  $file = $form_state['values']['file'];
  $file->status = FILE_STATUS_PERMANENT; // Изменяем статус файла на "Постоянный"
  file_save($file); // Сохраняем новый статус
  drupal_set_message('Картинка загружена');

  $staff = entity_ui_form_submit_build_entity($form, $form_state);
  $staff->save();
  $form_state['redirect'] = 'admin/structure/staffs';
  	
}

ошибка:
Картинка загружена
Error messageRecoverable fatal error: Object of class stdClass could not be converted to string in drupal_write_record() (line 6938 of C:\xampp\htdocs\corjeque\includes\common.inc).

перед entity_ui_form_submit_build_entity() сделайте unset($form_state['values']['file'])

Благодарю) Картинка загружается. По моему мнению - это самый полезный блог/ресурс по CMS Drupal.

Скажите, картинка которую я загрузил в форму, кидается в каталог,
А если создать для нее специальное поле в .install - blob и прописать его в форме, я смогу отобразить его черз theme('table'....)

а как при выводе информации обратится к файлу

foreach ($query as $staffs) 
		{
		$rows[] = array(
			check_plain($staffs->hid),
			check_plain($staffs->name),
			check_plain($staffs->post),
			check_plain($staffs->rank),
			check_plain($staffs->exp),
			check_plain($staffs->salary),
			$staffs->file,
	
	);
}

*обратиться
я имел ввиду: как вызвать файл из каталога друпал, для того чтобы отобразить его в конкретном материале. Мы же зачем то заполняли эту форму

milkovsky
05.09.2012, 22:47

Привет. Как можно поменять название файла при с помощью Form API ?

Александр
15.09.2013, 23:39

У меня у одного чтоле не работает?
Основная суть в том что в $_FILES имеем:
[code]
array(
'file' => array(
'name' => '13091023-short.txt',
'type' => 'text/plain',
'tmp_name' => '/tmp/phpME50PG',
'error' => 0,
'size' => 7642,
),
)
[/code]

в то время как в теле file_save_upload имеем:
[code]
if (empty($_FILES['files']['name'][$source])) {
return NULL;
}
[/code]

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

Александр
16.09.2013, 18:49

upd.

низя писать '#name', в этом все дело.

Гость
09.11.2013, 23:42

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

Гость
11.11.2013, 15:45

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

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

Михаил
26.08.2015, 21:58

Не подскажете, почему виджет загрузки файла меняет расширение загружаемого файла с расширением .js на .js.txt?

защита от заливки вредоносных файлов

Михаил
26.08.2015, 23:33

Спасибо. Это настраивается или только программно? Направьте, куда копать?

Гость
22.01.2016, 00:32

Как получить полный путь к загруженному файлу?

Гость
22.01.2016, 01:38

путь к файлу
$path = file_create_url($file->uri);
P.S.
file_create_url - формирует путь для скачивания файла.

Гость
03.02.2018, 16:10

Доброго дня!

Делаю кастомную форму, в ней использую поле типа multiupload image из типа материала...
Поле на форму добавляю через field_attach_form().

Все работает идеально, по ajax появляются миниатюры и т.д.

Но ест проблема:

если при добавлении картинок не нажать на кнопку ''Загрузка" и засабмитить форму, то в $form_state['values']['file_field'] пусто, нет фалов. С $form_state['input']['file_field'] такая же беда, и соответственно картинки не сохраняются.

При валидации тоже это поле пусто!

Если же нажимать кнопку ''Загрузить", то все работает нормально. Хотелось бы сделать по DrupalWay и не городить автозагрузки...

Пробовал грузить всю форму добавления ноды, в таком случае все работает как надо, но в моем случае вся форма не требуется.

Понимаю что чего-то форме не хватает, но не могу найти чего. Смотрел filefield модуль, но ничего толком не нашел...

Каким образом друпал подхватывает файлы из формы, без нажатия на кнопку Загрузить? Хотябы примерно натолкните на мысль, очень прошу...

Добавить комментарий