xandeadx.ru Блог музицирующего веб-девелопера

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

Опубликовано в

Пример загрузки картинки с помощью 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
Похожие записи

Комментарии RSS

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

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

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

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

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

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

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

'file[0]'

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

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

'attachment[' . $i . '][file]'

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

Возможно, вам интересно будет почитать:
http://drupal.org/node/83698

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

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

$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()

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

Спасибо!

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

наверное в том, что у вас drupal 6

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

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

 $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); 

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

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

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

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

А как реализовать, что бы в - 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).

вот в контексте

http://pastebin.com/eB4YM38W

перед 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,
 
	);
}

что значит "обратится"?

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

куда вызвать? если показать в браузере, то — http://htmlbook.ru/html/img

а если отображать в друпале, то http://xandeadx.ru/blog/drupal/538?

я вас не понимаю

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

* при загрузке с помощью Form API

Спасибо! ты мастер!

спасибки за пост

У меня у одного чтоле не работает?
Основная суть в том что в $_FILES имеем:

array(
  'file' => array(
    'name' => '13091023-short.txt',
    'type' => 'text/plain',
    'tmp_name' => '/tmp/phpME50PG',
    'error' => 0,
    'size' => 7642,
  ),
)

в то время как в теле file_save_upload имеем:

  if (empty($_FILES['files']['name'][$source])) {
    return NULL;
  }

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

upd.

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

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

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

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

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

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

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

Спасибо. Нашел обсуждение именно по моему вопросу http://stackoverflow.com/questions/1378246/drupal-filefield-wont-upload-javascript-files

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

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

Доброго дня!

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

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

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

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

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

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

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

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

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

Оставить комментарий

Содержимое этого поля является приватным и не будет отображаться публично. Если у вас есть аккаунт в Gravatar, привязанный к этому e-mail адресу, то он будет использован для отображения аватара.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступные HTML теги: <a> <i> <b> <strong> <code> <ul> <ol> <li> <blockquote> <em> <s>
  • Строки и параграфы переносятся автоматически.
  • Подсветка кода осуществляется с помощью тегов: <code>, <css>, <html>, <ini>, <javascript>, <sql>, <php>. Поддерживаемые стили выделения кода: <foo>, [foo].

Подробнее о форматировании