资讯专栏INFORMATION COLUMN

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

caiyongji / 1573人阅读

摘要:完整的模块代码文件在上,想直接使用的请前往下载最近吧部署到平台的时候,发现上传中文名的文件会出错。文件保存好,启用模块,就可以在文件保存之前,修改文件名,解决中文文件名出错的问题了。

完整的模块代码文件在Coding.net上,想直接使用的请前往下载:https://coding.net/u/yamus/p/...

最近吧Drupal8部署到Windows平台的时候,发现上传中文名的文件会出错。找了相关的模块,装上之后错误依旧。

后来发现错误是出在move_uploaded_file这一步的,也就是说必须在文件上传到服务器后,Drupal保存文件之前修改文件名,才能避免错误,于是仔细查看Drupal8关于文件处理方面的代码。发现表单的文件字段有一个#value_callback属性,可以设置文件上传后调用的方法。于是把这个属性替换成我自己写的方法。

首先建立一个模块,详细步骤就不说了。使用 hook_form_alter 修改字段的 #value_callback属性。

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"] = [
              "Drupalchinese_renameControllerChineseRenameController",
              "rename_chinese_filename"
            ];
          }
        }
      }
    }
  }
}
#value_callback属性是一个数组,前面是命名空间和类名,后面是方法名。

然后定义一个控制器,在模块目录的src/Controller目录下。控制器类里面定义一个处理文件名的方法,方法是静态的。这个方法接受三个参数。

一下是控制器的内容。

namespace Drupalchinese_renameController;

use DrupalCoreControllerControllerBase;
use DrupalCoreFormFormStateInterface;
use SymfonyComponentHttpFoundationFileUploadedFile;

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 DrupalfilePluginFieldFieldWidgetFileWidget::value($element, $input, $form_state);
  }
}

这里使用MD5处理中文文件名,也可以换成其他的方法。文件保存好,启用模块,就可以在文件保存之前,修改文件名,解决中文文件名出错的问题了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22520.html

相关文章

  • Drupal 8 结合Nginx实现文件上传进度,提高上传文件性能

    摘要:自带的上传进度功能,需要扩展支持。于是想到利用的模块来实现上传进度。接下来使用模块替代的文件上传功能,目的是提高文件上传的性能。而且可以避免上传大文件时执行超时引起错误。新建一个对象,把设置成刚上传的文件。 Drupal 8 自带的上传进度功能,需要PECL uploadprogress library扩展支持。安装后发现效果还是不太好,不知道什么原因,进度条不能正常显示,而且上传较大...

    SwordFly 评论0 收藏0
  • Drupal 8 结合Nginx实现文件上传进度,提高上传文件性能

    摘要:自带的上传进度功能,需要扩展支持。于是想到利用的模块来实现上传进度。接下来使用模块替代的文件上传功能,目的是提高文件上传的性能。而且可以避免上传大文件时执行超时引起错误。新建一个对象,把设置成刚上传的文件。 Drupal 8 自带的上传进度功能,需要PECL uploadprogress library扩展支持。安装后发现效果还是不太好,不知道什么原因,进度条不能正常显示,而且上传较大...

    keithxiaoy 评论0 收藏0
  • 编译安装Nginx以及配置运行Drupal 8,实现上传进度功能

    摘要:下载以及相关模块下载以及模块并解压。接着执行,即可完成编译安装。运行需要的配置首先需要在的上下文里增加一条这条是表示每上传就更新进度信息。 这篇文章的目的是在编译安装Nginx的同时,安装upload和uploadprogress模块,以及运行Drupal 8所需要的配置。由于使用的是Raspberry pi 3B,所以系统用的Raspbian,Debian/Ubuntu应该也是差不多...

    mist14 评论0 收藏0
  • godaddy主机怎么设置权限-godaddy上权限设置?

    摘要:上的权限设置登录帐号,进入控制面板,登录后点击。然后点击左边的下的,进入主机列表点击要设置权限的主机的标志进入控制面板,或者上方的进入文件管理设置权限之前,如图,先选中要设置权限的文件夹然后点进行读写权限设置,设置完成后点击保存。godaddy上的权限设置?登录Godaddy帐号,进入Godaddy控制面板,登录后点击MY Account。然后点击左边的My Products下的Hostin...

    dcr309duan 评论0 收藏0

发表评论

0条评论

caiyongji

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<