以编程方式在Drupal的文件系统中插入文件?

时间:2012-01-16 01:21:20

标签: drupal drupal-7

我正在使用CURL抓取一个文件,并希望将其保存在本地,但是它会插入到Drupal的文件系统中。我是否必须进行手动插入或是否有更好的方法?我能找到的最接近的是:

function image_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items);

但我不知道如何使用它。还有更好的建议吗?

3 个答案:

答案 0 :(得分:2)

有两种方法,但最简单的方法是使用file_save_upload()

$source = '/path/to/file.ext';
$dest = 'public://uploads/'; // Or whatever
$file = file_save_upload($source, array(), $dest, FILE_EXISTS_RENAME);

if ($file) {
  // file_save_upload marks the file as temporary, we need to mark as permanent or it will be cleared from the database in a few hours
  $file->status = FILE_STATUS_PERMANENT;
  file_save($file);
}

答案 1 :(得分:1)

这只是让我离开了我的脑海,试图找出一种简单的方法来规避表格API期望我遇到了这个问题。 Clive的答案是我如何弄清楚的开始,因为看起来你可以提供一个源作为file_save_upload()的第一个arg,但事实证明,你做不到。至少在目前的drupal 7.30中没有。

我检查了他提供的链接并解构了该功能。基本上,即使您传递完整的源路径,它仍然会在$ _FILES数组的路径中查找第一个arg。谁知道为什么,但多么愚蠢的想法。所以我这样做了:

//after verifying all post fields are set...
$node = new stdClass();
$node->type = 'user_files';
node_object_prepare($node);

$node->title    = $_POST['title'];
$node->author = 2; //hardcoded because only admin uses this form
$node->uid = 2;
$node->language = LANGUAGE_NONE;
$node->body[$node->language][0]['value']   = $_POST['body'];
$node->body[$node->language][0]['summary'] = text_summary($_POST['body']);
$node->body[$node->language][0]['format']  = 'filtered_html';

$node->field_first_name[$node->language][0]['value'] = $_POST['first_name'];
$node->field_last_name[$node->language][0]['value'] = $_POST['last_name'];

node_save($node);

if(isset($_FILES['file']['tmp_name']) && $_FILES['file']['name'] != '')
{
  //upload file

  $file = new stdClass();
  $file->uid = 2;
  $file->status = 0;
  $file->filename = trim(drupal_basename($_FILES['file']['name']), '.');
  $file->uri = $_FILES['file']['name'];
  $file->filemime = file_get_mimetype($file->filename);
  $file->filesize = $_FILES['file']['size'];
  $file->filename = file_munge_filename($file->filename, 'jpg jpeg gif png doc docx pdf');
  $file->destination = file_destination('private://' . $file->filename, FILE_EXISTS_RENAME);
  $file->uri = $file->destination;
  if (!drupal_move_uploaded_file($_FILES['file']['tmp_name'], $file->uri)) {

    return false; //set errors or do whatever you want on error
  }
  else
  {
    drupal_chmod($file->uri);
    $existing_files = file_load_multiple(array(), array('uri' => $file->uri));
    if (count($existing_files)) {
      $existing = reset($existing_files);
      $file->fid = $existing->fid;
    } 

    if ($file = file_save($file)) {
      // Add file to the cache.

      $node->field_file[$node->language][0]['uri'] = 'private://'.$file->filename;
      $node->field_file[$node->language][0]['fid'] = $file->fid;
      $node->field_file[$node->language][0]['display'] = 1;
      $node->field_file[$node->language][0]['description'] = 'User uploaded file';
      node_save($node);

      //do we notify someone?
    }    
  }
}

这样做会创建指定类型的节点。在这种情况下,user_files,然后如果上传文件,则将文件添加到媒体表,或文件表或其调用的任何内容。然后将关联添加到新创建的节点。

难看吗?是啊。为什么我不使用内部drupal表单API?闭嘴,这就是原因。我们并不总是有选择权,因此当客户要求提供只发送电子邮件的基本表单时,可以快速轻松地创建一个通过邮件黑猩猩API或其他内容发送的简单字段。然后他们补充说他们想要文件。然后他们希望它添加到drupal后端,突然间你会有一个恐怖的雪球,如果用表格API开始这样做会更容易。我不知道是谁开始的,但我不得不结束它,我用这个可怕的黑客做到了。希望它可以帮助你或其他任何人正在恐怖的drupal漩涡中旋转。

答案 2 :(得分:0)

我能够执行以下操作,使用file_savepublic:// Drupal文件夹(通常为sites/default/filessites/DOMAIN/files)添加文件。

$uri = 'public://filename.pdf';
$file = file_save((object) array(
  'filename' => basename($uri),
  'uri' => $uri,
  'status' => FILE_STATUS_PERMANENT,
  'filemime' => file_get_mimetype($uri),
));

这会在Drupal核心file_managed表中添加适当的条目。如果安装了File Entity模块,那么也会创建一个条目。

返回的文件对象将数据库ID包含为$file->fid