Drupal自定义模块中如何将提取的docx文件作为节点附件?
解决Drupal自定义模块中关联解压后docx文件为节点附件的问题
核心思路
你需要把解压后的本地docx文件转换成Drupal的File实体,再将实体关联到节点的文件字段,而不是直接传递SplFileInfo对象。下面是两种可行的实现方案:
方案一:从已有本地路径生成File实体
1. 转换本地路径为Drupal URI
Drupal识别文件依赖自身的URI格式(比如public://xxx),先把SplFileInfo对应的本地路径转成URI:
// $spl_file 是你拿到的SplFileInfo对象 $local_path = $spl_file->getRealPath(); // 获取public目录对应的服务器实际路径 $public_root = \Drupal::service('file_system')->realpath('public://'); $relative_path = str_replace($public_root, '', $local_path); $file_uri = 'public://' . ltrim($relative_path, DIRECTORY_SEPARATOR);
2. 创建并保存File实体
用Drupal的File实体类直接创建对象并保存:
$file = \Drupal\file\Entity\File::create([ 'uri' => $file_uri, 'filename' => $spl_file->getFilename(), 'filemime' => \Drupal::service('file.mime_type.guesser')->guess($file_uri), 'status' => FILE_STATUS_PERMANENT, // 标记为永久文件,防止被临时文件清理机制删除 ]); $file->save();
如果文件已经在Drupal管理的文件系统目录内,也可以用更简洁的方式生成File实体:
$file = file_save_data('', $file_uri, FILE_EXISTS_REPLACE);
3. 关联到节点字段
在你的createDecisionNode方法中,把File实体ID赋值给节点的文件字段:
// 假设节点的文件字段名为 field_doc_attachment $node->set('field_doc_attachment', [ 'target_id' => $file->id(), 'display' => 1, // 设置附件是否在前台显示 'description' => $spl_file->getFilename(), ]);
方案二:解压时直接写入Drupal文件系统
如果解压时就把文件放到Drupal管理的目录下(比如public://unzipped_docs/),后续生成File实体更顺畅:
- 提前创建并准备解压目录:
$unzip_dir = 'public://unzipped_docs/'; \Drupal::service('file_system')->prepareDirectory($unzip_dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
- 将zip包解压到该目录,后续直接用目录下的文件URI生成File实体即可。
关键注意事项
- 权限检查:确保解压后的文件目录和文件有web服务器用户的读写权限,必要时用
\Drupal::service('file_system')->chmod($file_uri, 0644)调整权限 - 重复文件处理:如果存在同名文件,
file_save_data的第三个参数可改用FILE_EXISTS_RENAME避免覆盖原有文件 - 临时文件清理:处理完成后,记得删除用户上传的原zip临时文件(如果是临时状态):
file_delete($original_zip_file)
内容的提问来源于stack exchange,提问作者Chris Costa
相关产品推荐
相关产品推荐

