Drupal 7中重复文件名的PDOException

时间:2012-01-10 19:07:43

标签: drupal drupal-7

使用以下代码:

foreach ($form_state['values']['uploads'] as $key => $value) {
if (strlen($value)) {
  $file = file_save_upload($key, array(
    'file_validate_is_image' => array(), // Validates file is really an image. 
    'file_validate_extensions' => array('png gif jpg jpeg'), // Validate extensions.
  ));
  // If the file passed validation:
  if ($file) {
    // Move the file, into the Drupal file system
    if ($file = file_move($file, 'public://')) {
     // Save the file for use in the submit handler.
     $form_state['values']['uploaded_photos'][] = $file;
             $x++;
    } else {
     form_set_error($key, t('Failed to write the uploaded file the site\'s file folder.'));
    }
  }
}

}

我正在尝试使用CTools将附加到表单的图像保存到缓存对象中。所有这一切都运行良好,直到我再次尝试上传相同的文件,我得到一个白色的屏幕,上面写着“错误 - 网站遇到错误。” (从看门狗身上撕掉):

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'public://ad-10.jpg'; for key 2: UPDATE {file_managed} SET uid=:db_update_placeholder_0, filename=:db_update_placeholder_1, uri=:db_update_placeholder_2, filemime=:db_update_placeholder_3, filesize=:db_update_placeholder_4, status=:db_update_placeholder_5, timestamp=:db_update_placeholder_6
WHERE  (fid = :db_condition_placeholder_0) ; Array
(
[:db_update_placeholder_0] => 0
[:db_update_placeholder_1] => ad-10.jpg
[:db_update_placeholder_2] => public://ad-10.jpg
[:db_update_placeholder_3] => image/jpeg
[:db_update_placeholder_4] => 4912
[:db_update_placeholder_5] => 0
[:db_update_placeholder_6] => 1326221376
[:db_condition_placeholder_0] => 834
)
";s:9:"%function";s:21:"drupal_write_record()";

由于我没有设置$ replace参数,它不应该默认为FILE_EXISTS_RENAME,因此不会抛出此错误吗?我该如何解决这个问题?

3 个答案:

答案 0 :(得分:6)

试试这个模块。它修复了写入db的并发文件对象的问题。 https://drupal.org/project/upload_qc

答案 1 :(得分:2)

我不能评论为什么它不起作用(它看起来肯定应该)但我可以提供一个更简单的解决方案。

Drupal实际上有一个内置的表单小部件来处理文件上传,managed_file类型。它为您处理所有文件上传/验证,您只需要在表单的提交处理程序中将文件标记为永久文件。

所以在你的表单函数中:

$form['files'] = array('#tree' => TRUE);

for ($i = 0; $i < $num_file_fields; $i++) {
  $form['files']["file_$i"] = array(
    '#type' => 'managed_file',
    '#title' => 'Select a file',
    '#upload_location' => 'public://',
    '#upload_validators' => array(
      'file_validate_is_image' => array(),
      'file_validate_extensions' => array('png gif jpg jpeg')
    )
  );
}

然后在你的提交处理程序中:

$count = count($form_state['values']['files']);

for ($i = 0; $i < $count; $i++) {
  $file = file_load($form_state['values']['files']["file_$i"]);
  $file->status = FILE_STATUS_PERMANENT;
  file_save($file);
}

希望有所帮助

答案 2 :(得分:1)

由于奇怪的未使用的临时文件,我遇到了同样的问题。 您可以使用以下方法检查是否有未使用的文件:

$result = db_select('file_managed', 'f')
    ->fields('f', array('fid'))
    ->condition('f.uri', db_like('temporary://') . '%', 'LIKE')
    ->execute()->fetchCol();

foreach ($result as $fid) {
  if ($file = file_load($fid)) {
    if (!file_usage_list($file)) {
      dpm($file->filename);
    }
  }
}

如果您无法上传与您看到的名称相同的文件,则可以将其删除(先仔细检查并备份):

/**
 * Clean unused temporary files.
 */
function MYMODULE_update_7007() {
  $files = db_select('file_managed', 'f')
    ->fields('f', array('fid'))
    ->condition('f.uri', db_like('temporary://') . '%', 'LIKE')
    ->execute()->fetchCol();
  foreach ($files as $fid) {
    if ($file = file_load($fid)) {
      $references = file_usage_list($file);
      if (empty($references)) {
        if (!file_delete($file)) {
          watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->uri), WATCHDOG_ERROR);
        }
      }
      else {
        watchdog('file system', 'Did not delete temporary file "%path" during garbage collection, because it is in use by the following modules: %modules.', array('%path' => $file->uri, '%modules' => implode(', ', array_keys($references))), WATCHDOG_INFO);
      }
    }
  }
}