Drupal 8 重命名上傳的中文名文件

完整的模塊代碼文件在Coding.net上,想直接使用的請前往下載:https://coding.net/u/yamus/p/...git

最近吧Drupal8部署到Windows平臺的時候,發現上傳中文名的文件會出錯。找了相關的模塊,裝上以後錯誤依舊。數組

後來發現錯誤是出在move_uploaded_file這一步的,也就是說必須在文件上傳到服務器後,Drupal保存文件以前修改文件名,才能避免錯誤,因而仔細查看Drupal8關於文件處理方面的代碼。發現表單的文件字段有一個#value_callback屬性,能夠設置文件上傳後調用的方法。因而把這個屬性替換成我本身寫的方法。服務器

首先創建一個模塊,詳細步驟就不說了。使用 hook_form_alter 修改字段的 #value_callback屬性。spa

function chinese_rename_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  # 檢查文件名
  # 獲取表單內全部Element
  $els = Element::children($form);
  foreach($els as $elName) {
    if(isset($form[$elName]['widget'])) {
      foreach($form[$elName]['widget'] as $w => $widget) {
        if(is_numeric($w)) {
          if(@$form[$elName]['widget'][$w]['#type'] == 'managed_file') {
            $form[$elName]['widget'][$w]['#value_callback'] = [
              'Drupal\chinese_rename\Controller\ChineseRenameController',
              'rename_chinese_filename'
            ];
          }
        }
      }
    }
  }
}
#value_callback屬性是一個數組,前面是命名空間和類名,後面是方法名。

而後定義一個控制器,在模塊目錄的src/Controller目錄下。控制器類裏面定義一個處理文件名的方法,方法是靜態的。這個方法接受三個參數。.net

一下是控制器的內容。code

namespace Drupal\chinese_rename\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class ChineseRenameController extends ControllerBase {
  // 重命名中文文件名
  public static function rename_chinese_filename(&$element, $input, FormStateInterface $form_state) {
    # 若是提交新的文件
    if(!is_numeric($input['fids'])) {
      $form_field_name = implode('_', $element['#parents']);
      $all_files = \Drupal::request()->files->get('files', array());
      
      // Make sure there's an upload to process.
      if (empty($all_files[$form_field_name])) {
        return NULL;
      }
      $file_upload = $all_files[$form_field_name];
      // Prepare uploaded files info. Representation is slightly different
      // for multiple uploads and we fix that here.
      $uploaded_files = $file_upload;
      if (!is_array($file_upload)) {
        $uploaded_files = array($file_upload);
      }
      $files = array();
      $destination = 'temporary://';
      $realPath = \Drupal::service('file_system')->realpath($destination);
      foreach ($uploaded_files as $i => $file_info) {
        # 把源文件對象替換成重命名過的文件對象
        $originalName = $file_info->getClientOriginalName();
        if(preg_match("/[\x7f-\xff]/", $originalName)) {
          $newName = md5($originalName) . '.' . $file_info->getClientOriginalExtension();
          # 新建一個上傳文件對象
          $newFile = new UploadedFile(
            $file_info->getRealPath(),
            $newName,
            $file_info->getClientMimeType(),
            $file_info->getClientSize(),
            $file_info->getError()
          );

          if(count($uploaded_files) <= 1) { $uploaded_files = $newFile; } else { $uploaded_files[$i] = $newFile; } } } $all_files[$form_field_name] = $uploaded_files; \Drupal::request()->files->set('files', $all_files);
    }
    
    # 調用默認文件處理方法
    return \Drupal\file\Plugin\Field\FieldWidget\FileWidget::value($element, $input, $form_state);
  }
}

這裏使用MD5處理中文文件名,也能夠換成其餘的方法。文件保存好,啓用模塊,就能夠在文件保存以前,修改文件名,解決中文文件名出錯的問題了。orm

相關文章
相關標籤/搜索