Saving a remote image programmatically with PHP - php

I am trying to migrate some content from one resources into another and need to save some images (several hundred) located at a remote resource.
Suppose I have only the URL to an image:
https://www.example.com/some_image.jpg
And I would like to save it into the filesystem using PHP.
If I were uploading the image, I essentially would do the following:
<input type="file" name="my_image" />
move_uploaded_file($_FILES['my_image']['tmp_name'], '/my_img_directory');
But since I only have the URL, I would imagine something like:
$img = 'https://www.example.com/some_image.jpg';
$file = readfile($img);
move_uploaded_file($file, '/my_img_directory');
Which of course wouldnt work since move_uploaded_file() doesn't take an output buffer as a first argument.
Essentially, I would need to get $img into the $_FILES[] array under this approach. Or may some other approach?

You can use PHP's copy function to copy remote files to a location on your server:
copy("https://example.com/some_image.jpg", "/path/to/file.jpg");
http://php.net/manual/en/function.copy.php

$image = file_get_contents('http://www.url.com/image.jpg');
file_put_contents('/images/image.jpg', $image); //Where to save the image on your server

Related

img php src asynchronous

If I use php file as source to image, where:
$file = $_GET["file"];
$file_get = get_file_contents("from/".$file);
$fopen = fopen("to/".$file,"w+");
fwrite($fopen, $file_get);
fclose($fopen);
header("Location:to/".$file);
And if I use many images of that kind on one page, like:
<img src="image.php/?file=img.jpg>
<img src="image.php/?file=img2.jpg>
<img src="image.php/?file=img3.jpg>
...
I found that code in image.php doesn't run asynchronously. Images are downloaded one by one. How can I avoid it?
I see there some problems in your code. The first is that you have a big security whole when you use the $_GET input directly in your code to get an image.
The next one is why do you fetch the content from one file and write them to another file to redirect to them? That is not really fast if you write every time the file to another location.
If you get the content echt echo the content and set the correct header to show the image.
header('Content-type:image/png');
readfile($fullpath);
Its much easier and you have a less IO to show files. Otherwise you can use a script like PHPThumb which generated smaller versions and cache the files.
http://phpthumb.sourceforge.net/

how to retrieve blob file to image in php?

I am using plupload to upload file in my php based website, with large file uploading the file becomes a file named 'blob' without any suffix. I know this is a binary file that contains the raw data, question is how to retrieve the data and save it back as an image file, say .png/.jpg or etc? I tried:
$imageString = file_get_contents($blogPath);
$image = imagecreatefromstring($imageString);
But it gives me some 'Data is not in recognized format...' error, any thoughts? Thanks in advance.
Your call to imagecreatefromstring() should work just fine if your file_get_contents() is working. Use var_dump($imageString) to verify. Did you mean to name your variable $blobPath instead of $blogPath?
You don't need to load this image though. Just rename the file.
rename($blobPath, 'new/path/here.jpg');
http://php.net/manual/en/function.rename.php
I am storing the uploaded image files for late use, like attaching them to posts or products(my site is e-commerce CMS). I figured that my image file didn't get fully uploaded to the server, the image before upload is 6mb, but the blob file is just 192kb, so my best guess is that what get uploaded is just a chunk instead of the whole package, and yet that brought up another question: how should I take all the pieces and assemble them as one complete image file? As mentioned earlier, I am using plupload for js plugin and php as backend, the backend php code to handle uploading goes like this:
move_uploaded_file($_FILES["file"]["tmp_name"], $uploadFolder . $_FILES["file"]["name"]);
Instead of doing that you should do this to display image to the browser
<img src="data:image/jpeg;base64,'.base64_encode( $row['blob_image'] ).'"/>
I'm not sure what imagecreatefromsting does or how it encodes the image.
I looked at the documentation for that function; you're missing:
$data = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
. 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
. 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
. '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$data = base64_decode($data); <--- this operation

Display user input image without saving it to a folder

How can I display an image and pass it as an input parameter in an executable in php without saving the image in a folder. The user gives the image path as input and I am using ajax to display the image when it is selected when I save it to a folder it works but how can I display it without saving it in a folder? My code now is
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]);
//echo "Stored in "."upload/".$_FILES["file"]["name"];
echo "<img src='upload/".$_FILES["file"]["name"]."' class='preview'>";
I tried
<img src=$_FILES["file"]["tmp_name"]. class='preview'>
but it didnt work. As I will have thousands of input from thousands of user I dont want to save it. Is there any optimised and efficient method to do this?
I think, its not possible to show image without saving it. You could try to save the image in temp folder on the server side and clean this folder periodically to avoid much space consumption.
The src attribute of the <img> tag should be an URL accessible by the client.
You try to give a local path (ex: path/to/your/file.jpg) of a temporary file as URL, it will not working.
info: The uploaded image is save on the local disk on a temp directory, and could be deleted by PHP later.
If you want to show the image without moving it at a place reacheable by a URL, you can try to load its content as base64 content
$imagedata = file_get_contents($_FILES["file"]["tmp_name"]);
$base64 = base64_encode($imagedata);
and use in your HTML
<img src="data:image/png;base64, <?php echo $base64; ?>" />
I don't think you can show the image without saving it.
You need to save the file either to the filesystem or to memory if you want to later output
Your problem here is that $_FILES only exists in the script that the image was sent to. so when you initiate another http request for img source, php no longer has any clue what file your trying to read.
You need a way to tell which image to be read on http request.
One thing you can do is that you can save the file in a place accessible by the client and then just have php delete it after you output it. So once the image is outputted it will be deleted and no longer be existing in the file system.
Another approach would be to get the image from the memory by directly writing the contents to httpresponse.
You can do this way
$image = file_get_contents($_FILES["file"]["tmp_name"]);
$enocoded_data = base64_encode($image);
and when you show your image tag :
<img src="data:image/png;base64, <?php echo $enocoded_data ; ?>" />
Hope any of these helps you

PHP: Storing picture in the file directory, image name in db and retrieving an image

After doing research, I found that it is more recommended to save the image name in database and the actual image in a file directory. Two of the few reasons is that it is more safer and the pictures load a lot quicker. But I don't really get the point of doing this procedure because every time I retrieve the pictures with the firebug tool i can find out the picture path in the file directory which can lead to potential breach.
Am I doing this correctly or it is not suppose to show the complete file directory path of the image?
PHP for saving image into database
$images = retrieve_images();
insert_images_into_database($images);
function retrieve_images()
{
$images = explode(',', $_GET['i']);
return $images;
}
function insert_images_into_database($images)
{
if(!$images) //There were no images to return
return false;
$pdo = get_database_connection();
foreach($images as $image)
{
$path = Configuration::getUploadUrlPath('medium', 'target');
$sql = "INSERT INTO `urlImage` (`image_name`) VALUES ( ? )";
$prepared = $pdo->prepare($sql);
$prepared->execute(array($image));
echo ('<div><img src="'. $path . $image . '" /></div>');
}
}
One method to achieve what you originally intended to do by storing images in database is still continue to serve image via a PHP script, thus:
Shielding your users from knowing the actual path of an image.
You can, and should have, images stored outside of your DocumentRoot, so that they are not able to be served by web server.
Here's one way you can achieve that through readfile():
<?php
// image.php
// Translating file_id to image path and filename
$path = getPathFromFileID($_GET['file_id']);
$image = getImageNameFromFileID($_GET['file_id']);
// Actual full path to the image file
// Hopefully outside of DocumentRoot
$file = $path.$image;
if (userHasPermission()) {
readfile($file);
}
else {
// Better if you are actually outputting an image instead of echoing text
// So that the MIME type remains compatible
echo "You do not have the permission to load the image";
}
exit;
You can then serve the image by using standard HTML:
<img src="image.php?file_id=XXXXX">
You can use .htaccess to protect your images.
See here:
http://michael.theirwinfamily.net/articles/csshtml/protecting-images-using-php-and-htaccess
I'm also working on a project which stores the url path of images on the database (Amazon RDS) and the actual images in a cloud managed file system in Amazon S3.
The decision to do so came primarily with the concern of price, scalability and ease of implementation.
Cheaper: Firstly, it is cheaper to store data in a file system (Amazon S3) compared to a database (Amazon EC2 / RDS).
Scalable: And since the repository of images may grow pretty big in the future, you might also need to ensure that you have the adequate capacity to serve them. On this point, it is easier to scale up a filesystem compared to a database. In fact, if you are using cloud storage (like Amazon S3), you don't even need to worry about having not enough space as it has been managed for you by Amazon! you would just need to pay for what you use.
Ease of Implementation: In terms of implementation, storing images in a file system is much easier. If you were to serve images directly from databases, you would probably need to implement additional logic to convert blob files into html src blob strings to serve images. And from the look of it, this might actually take up quite substantial processing power which might slow your web server down.
On the other hand, if you were to use a filesystem, all you would require is to put down the url path of the image from the database to the src attribute of the image and its all done!
Security: As for security of the images, i have changed the image name to a timestamp concatenated with a random string so that it will prove really difficult for someone to browse for pictures without knowing the file name.
ie. 1342772480UexbblEY7Xj3Q4VtZ.png
Hope this helps!
NB: Please edit my post if you find anything wrong here! this is just my opinion and everyone is welcome to edit!

Resize image directly from Rackspace Cloud Files 'object' without downloading?

I have moved my images to Rackspace Cloud Files and am using their PHP API. I am trying to do the following:
Get an image from my "originals" container
Resize it, sharpen it, etc.
Save the resized image to the "thumbs" container
My problem is with #2. I was hoping to resize without having to copy the original to my server first (since the images are large and I'd like to resize dynamically), but can't figure out how. This is what I have so far (not much):
$container = $conn->get_container("originals");
$obj = $container->get_object("example.jpg");
$img = $obj->read();
Part of the problem is I don't fully understand what is being returned by the read() function. I know $img contains the object's "data" (which I was able to print out as gibberish), but it is neither a file nor a url nor an image resource, so I don't know how to deal with it. Is it possible to convert $img into an image resource somehow? I tried imagecreatefromjpeg($img) but that didn't work.
Thanks!
First, you cannot resize an image without loading it into memory. Unless the remote server offers some "resize my image for me, here are the parameters" API, you have to load the image in your script to manipulate it. So you'll have to copy the file from the CloudFiles container to your server, manipulate it, then send it back into storage.
The data you receive from $obj->read() is the image data. That is the file. It doesn't have a file name and it's not saved on the hard disk, but it is the entire file. To load this into gd to manipulate it, you can use imagecreatefromstring. That's analogous to using, for example, imagecreatefrompng, only that imagecreatefrompng wants to read a file from the file system by itself, while imagecreatefromstring just accepts the data that you have already loaded into memory.
You can try to dump the content of the $img variable into a writable file as per the below:
<?php
$filename = 'modifiedImage.jpg';
/*
* 'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate
* the file to zero length. If the file does not exist, attempt to create it.
*/
$handle = fopen($filename, 'w+');
// Write $img to the opened\created file.
if (fwrite($handle, $img) === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
echo "Success, wrote to file ($filename)";
fclose($handle);
?>
More details:
http://www.php.net/manual/en/function.fopen.php
http://www.php.net/manual/en/function.fwrite.php
Edit:
You might also want to double check the type of data returned by the read() function, because if the data is not a jpg image, if it's for example a png, the extension of the file needs to be changed accordingly.

Categories