20

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.

0

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. – Dave Reid Jul 3 '13 at 14:53
13

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

  • 7
    Actually 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); – Dave Reid Jul 3 '13 at 14:56
6

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 in FILE_STATUS_PERMANENT? I don't see the point of your custom function? – mpdonadio Jan 29 '14 at 20:11
  • In that way - I don't have problems with big files. – hugronaphor Jan 30 '14 at 20:01
1

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.

1
// 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 where file_get_contents() isn't available)? – Clive Oct 2 '13 at 15:44
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.