来源:https://blog.mulin.tech/archives/20

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

最近吧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'] = [
'Drupal\chinese_rename\Controller\ChineseRenameController',
'rename_chinese_filename'
];
}
}
}
}
}
}

#value_callback属性是一个数组,前面是命名空间和类名,后面是方法名。

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

 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处理中文文件名,也可以换成其他的方法。文件保存好,启用模块,就可以在文件保存之前,修改文件名,解决中文文件名出错的问题了。

最新文章

  1. Npm install failed with “cannot run in wd”
  2. Tools - Docker与Vagrant
  3. 安装切换openjdk
  4. NOI 09:奇数求和
  5. c语言的学习秘籍之链表
  6. (document).height()、$(document).scrollTop()
  7. coursera机器学习-支持向量机SVM
  8. KVM虚拟机内存不足,调整参数
  9. ubuntu安装android开发环境
  10. getWindow().setFlags
  11. 使用Aspose.Cell控件实现Excel高难度报表的生成(三)
  12. ServiceStack.OrmLite 笔记5 改
  13. SharePoint 2013 Nintex Workflow 工作流帮助(四)
  14. Android(java)学习笔记235:多媒体之计算机图形表示方式
  15. myeclipse 不能添加非myeclipse开发的项目
  16. 【DDD】领域驱动设计实践 —— 业务建模实例(‘发布帖子’)
  17. Qt websocket
  18. 转:Eclipse中web项目部署至Tomcat步骤
  19. java基础----&gt;String和MessageFormat的format方法
  20. 2017-3-31/socket

热门文章

  1. OpenCV2.4.13+VS2013开发环境配置
  2. 域名解析服务查询工具dnstracer
  3. Linux usual cmd
  4. 采用Lambda表达式快速实现实体模型对象转换到DTO
  5. mysql开启远程访问权限
  6. 深入理解JavaScript运行机制
  7. Windows中断那些事儿
  8. web前端笔试选择题
  9. 关于html5新增的功能(百度)
  10. 基于黑名单的xss过滤器