tutorial - ¿Inserta programáticamente un archivo en el sistema de archivos de Drupal?
drupal 7.59 download (3)
Estoy tomando un archivo usando CURL, y quiero guardarlo localmente, pero entonces se conecta al sistema de archivos de Drupal. ¿Tendría que hacer una inserción manual o hay una mejor manera? Lo más cerca que pude encontrar fue:
function image_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items);
Pero no sé cómo usar esto. ¿Alguna mejor sugerencia?
Hay un par de formas, pero la más fácil sería usar 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);
}
Esto casi me saca de mi mente y al tratar de encontrar una forma simple de eludir las expectativas de la API de forma me encontré con esta pregunta. La respuesta de Clive fue el comienzo de cómo lo descubrí porque parece que puedes proporcionar una fuente como primer argumento para file_save_upload (), pero resulta que no puedes. Al menos no en el drupal actual 7.30.
Revisé el enlace que él proporcionó y deconstruí la función. Básicamente, incluso si pasa una ruta de fuente completa, aún busca la primera arg en la matriz $ _FILES a lo largo de la ruta. Quién sabe por qué, pero qué idea tan tonta. Entonces hice esto:
//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?
}
}
}
Lo que hace esto es crear un nodo de un tipo especificado. En este caso, user_files, luego si se carga un archivo, agregue el archivo a la tabla de medios, o tabla de archivos o como se llame. Luego agrega la asociación al nodo recién creado.
¿Es feo? Sí. ¿Por qué no utilicé la API interna de drupal? Cállate, es por eso. No siempre tenemos una opción, por lo que cuando un cliente solicita un formulario básico que simplemente los envía por correo electrónico, es fácil y rápido crear un campo simple que envíe a través de una API chimpancé de correo o algo así. Luego, más tarde agregan que quieren archivos. Luego, más tarde, quieren que se agregue a la parte posterior de drupal y de repente tienes una bola de nieve de terror que hubiera sido mucho más fácil si se hubiera hecho con la API de formulario para empezar. No sé quién comenzó, pero tuve que terminarlo y lo hice con este truco horrible. Espero que te ayude a ti o a quien sea que esté girando actualmente en el vértice de horror de Drupal.
Pude hacer lo siguiente para agregar un archivo del public://
carpeta Drupal (típicamente sites/default/files
o sites/DOMAIN/files
) usando file_save
.
$uri = ''public://filename.pdf'';
$file = file_save((object) array(
''filename'' => basename($uri),
''uri'' => $uri,
''status'' => FILE_STATUS_PERMANENT,
''filemime'' => file_get_mimetype($uri),
));
Esto agrega la entrada apropiada en la tabla Drupal core file_managed
. Si tiene instalado el módulo de Entidad de Archivo , también se crea una entrada allí.
El objeto de archivo devuelto incluirá la ID de la base de datos como $file->fid
.