I want to programmatically add an image from an external URL and have the module store and display a local copy of the image. How can I do that? Normally, I would click the "select media" button while creating a new node but I want to do it through code.
6 Answers
This is a partial answer to your question, as I'm trying to do something similar but with video material.
You could create the node as a content type, save the media type that you need (have a look through the media code for the relevant mime/type and functions that you need to call). You will probably need to set a multimedia asset field and use the media file selector in the field type.
The bit I'm having an issue with is getting the browser to show it in the created node though, which I'm currently working through.
UPDATE
Having got a bit further. Once you have saved the media file (using media API), associate the file id with the node ID using file_usage_add(). You'll probably also need to associate the file in the field added when you created the media asset field.
-
You do not need to call file_usage_add(). You just need to add the file to a field like is shown in tecjam's answer. Jul 3, 2013 at 14:53
Make sure your php.ini allows allow_url_fopen. Then you can use something like this in your module:
$image = file_get_contents('http://drupal.org/files/issues/druplicon_2.png'); // string
$file = file_save_data($image, 'public://druplicon.png',FILE_EXISTS_REPLACE);
Use php's file_get_contents() function
http://www.php.net/manual/en/function.file-get-contents.php
and then use Drupal API's file_save_data()
http://api.drupal.org/api/drupal/includes--file.inc/function/file_save_data/7
Then you should be able to call it using and save it to a node etc ..
$node = new stdClass;
$node->type = 'node_type';
node_object_prepare($node);
$node->field_image[LANGUAGE_NONE]['0']['fid'] = $file->fid;
node_save($node);
Edit:
As pointed out in the comments, you can use function system_retrieve_file See: https://api.drupal.org/api/drupal/modules!system!system.module/function/system_retrieve_file/7
-
9Actually there is a better API for this: system_retrieve_file()
$file = system_retrieve_file('http://drupal.org/files/issues/druplicon_2.png', NULL, TRUE, FILE_EXISTS_RENAME);
Jul 3, 2013 at 14:56
Here is my working example.
$remoteDocPath = 'http://drupal.org/files/issues/druplicon_2.png';
$doc = system_retrieve_file($remoteDocPath, NULL, FALSE, FILE_EXISTS_REPLACE);
$file = drupal_add_existing_file($doc);
$node = new stdClass;
$node->type = 'node_type';
node_object_prepare($node);
$node->field_image[LANGUAGE_NONE]['0']['fid'] = $file->fid;
node_save($node);
function drupal_add_existing_file($file_drupal_path, $uid = 1, $status = FILE_STATUS_PERMANENT) {
$files = file_load_multiple(array(), array('uri' => $file_drupal_path));
$file = reset($files);
if (!$file) {
$file = (object) array(
'filename' => basename($file_drupal_path),
'filepath' => $file_drupal_path,
'filemime' => file_get_mimetype($file_drupal_path),
'filesize' => filesize($file_drupal_path),
'uid' => $uid,
'status' => $status,
'timestamp' => time(),
'uri' => $file_drupal_path,
);
drupal_write_record('file_managed', $file);
}
return $file;
}
-
Why are you creating a temporary file with the
system_retrieve_file()
and then saving it as a permanent one inFILE_STATUS_PERMANENT
? I don't see the point of your custom function?– mpdonadio ♦Jan 29, 2014 at 20:11 -
This isn't a direct answer, but make sure that you already know about the Filefield Sources module, which does this for images in general. It might meet your needs on its own; I don't know if it's useful with Media.
As addition to @tecjam answer: you should use drupal_http_request() instead of file_get_contents(), it gives you more control over process. But in total this method works as expected.
// This is a PHP function to get a string representation of the image file.
$image = file_get_contents($path);
// A stream wrapper path where you want this image to reside on your file system including the desired filename.
$destination = 'public://path/to/store/this/image/name.jpg';
$file = file_save_data($image, $destination, FILE_EXISTS_REPLACE);
if (is_object($file)) { // if you get back a Drupal $file object, everything went as expected so make the status permenant
$file->status = 1;
$file = file_save($file);
}
return $file;
-
Any reason to use that method over
system_retrieve_file()
(which does it all for you and avoids problems with servers wherefile_get_contents()
isn't available)?– Clive ♦Oct 2, 2013 at 15:44