php copy issue with foreach loop-only last image being uploaded - php

i am trying to upload remote file using below code for testing purpose and to my surprise only last images are being uploaded.. i changed the sequence of images and it was always last image which was uploading rest are failing. inbrowser console i can see below error.
Warning: copy(http://example.com/your-heart.jpg
): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/example/minimum.php on line 205
it is coming from form with text field name is urls
here is my php
$image_links = explode("\n", $_POST['urls']);
$i = 1;
foreach($image_links as $image_link){
$file_info = pathinfo($image_link);
copy($image_link, '/home/xxxxx/00' . $i . '_original.' . $file_info['extension']);
$i++;
}
any help will be great.
i tried so many different things for copy parameters like single quote, double quote and several other things but always same output. only last image upload and it says all other images are not found. i even tried to replace http with www . my sample urls are
http://example.com/color-your-heart.jpg
output of var dump
array(2) {
[0]=>
string(61) "http://example.com/thumb/color-your-heart.jpg
"
[1]=>
string(64) "http://example.com/thumb/mobile-price-real-time-calculator.png"
}

It looks like there's a space after the filename in the error message. Try removing spaces with trim()
copy(trim($image_link), '/home/xxxxx/00' . $i . '_original.' . $file_info['extension']);

I always use like below.
$image_data = file_get_contents($image_url);
$fileext = 'jpg'; // ext
$thenew_name = 'new random name or something';
$file = $upload_dir . '/' . $thenew_name . '.' . $fileext;
file_put_contents($file, $image_data);
Then use $file with additional relative directory path to save the image for you, like replace $upload_dir with your path variable. You can use into your foreach loop also. Also remove all the extra pert from image url. Most of expert said you in comments.

Related

Converting images to greyscale using intervention

I am trying to convert my images into greyscale and then downloading it in Laravel but each and every time I am getting this error
The file "" does not exist
Dont' know why it giving this error here is my code.
$file = public_path() . "/large/s/" . $sheet[0]->sheet_f_id . '-s.jpg';
$image = Image::make($file);
$grayScale = $image->greyscale();
return Response::download($grayScale);
When I dump my $file variable I got the response something like this.
"D:\xampp\htdocs\wikistaging\public/large/s/03-02-05-025-s.jpg"
But still it is giving me the sam error why is that happening. Any help would be great.
If you want to download then first you have to save the created file and need to give the path to download. Here is working example
$img_name=$sheet[0]->sheet_f_id . '-s.jpg';
$destination_path=public_path() . "/large/s/";
$file = $destination_path.$img_name;
$image = Image::make($file);
$image->greyscale()->save($destination_path.'gray-'.$img_name);
return Response::download($destination_path.'gray_'.$img_name);
And if you don't want to keep the file you can delete, replace the last line with below line.
return Response::download($destination_path.'gray_'.$img_name)->deleteFileAfterSend(true);
Hope it will work for you.
You must save your image after call greyscale().
You can try it:
$filePath = public_path() . "/large/s/" . $sheet[0]->sheet_f_id . '-s-test.jpg';
$image->greyscale();
$image->save($filePath);

PHP/Laravel file existence verification not working

I have a <form> with a multiple file input that stores those files into the server. The names of the files must follow a numeric standard and that's why I rename them before storing. Each post has an ID an can have more than one file so the pattern is: post-id + dash and a number + file extension, this way, if the same post has two file with the same extensions, the dash + number will avoid them to be overwriten. So, before I store the files I run a loop to find the proper number to the name. The problem is, the function to verify the existence of the file seems not to be returning true when it should. The code:
$counter = 0;
do{
$nomeArquivo = $post->id . "-{$counter}" . "." . $arq->extension();
$counter++;
//these commented are other ways of verification I tried
//}while(Storage::exists($nomeArquivo));
//}while(file_exists("/storage/" . $nomeArquivo));
}while(is_file("/storage/" . $post->id . "-{$counter}"));
Storage::putFileAs('/public', $arq, $nomeArquivo);
This code above runs inside a foreach($files as $arq) where $files are the files from the form input.
Reference: https://laravel.com/docs/5.4/filesystem and https://laravel.com/api/5.4/Illuminate/Filesystem/Filesystem.html
Use the File Facade to check for the existence of a file:
File::exists($myfile)
http://laravel-recipes.com/recipes/123/determining-if-a-file-exists
If name of the file need to be unique only then,
You can give Unique Name like this:
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$destination ='/files/';
$filename = uniqid() . '.' . $extension;
$file->move($destination, $filename);
Now save above file name in your database. Hope it may help you
As user #fubar pointed in the comments, I was referencing the wrong path to verify the existence of the file. I change the while condition to while(\File::exists(public_path() . '/storage/' . $nomeArquivo)) and it worked well. Thanks

How to download images from various URL (same path)

I want to download about 200 images from an URL. For instance: Fetch www.web.com/images/001.png and download, fetch www.web.com/images/002.png and download and finish in 200.png.
I've read Grab/download images from multiple pages using php preg_match_all & cURL but I don't know how to modify the PHP to do that thing.
I'll be very appreciated if you can help me. Thank you so much
The simplest way that comes to mind, is to create a for loop, which counts from 1 to 200 and for every count, it then does a request for the image and saves it to the disk (I assume you want to save the image to your disk). Working example can be found at the bottom.
Let's start by settings some variables:
$baseUrl = 'http://www.web.com/';
$localDirectory = 'downloaded_images/';
$maxImageNumber = 200;
The first variable $baseUrl defines where the images will be loaded from. The second defines your local directory in which the images will be saved. Please make sure that this directory exists before running the code, because it will not be automatically generated. The last variable, $maxImageNumber stores the largest image number, which we will need for the for loop.
After setting the variables, we can write the for loop. Separated by semicolons ; there are three parts in the brackets. First one being the starting point of the number we will be counting upwards. The second makes sure we don't go over our limit and the last one just states that the number will be counted up, using the ++ shorthand.
for($imageNumber = 1; $imageNumber <= $maxImageNumber; $imageNumber++) {
// code goes here
}
Inside this for loop we can now generate our file name and download/save the image to the disk. The first line uses the function str_pad() to add leading 0s to the image file (just like in your example) and then adds the extension .png to the name. This allows us to reuse the file name for loading as well as for saving. Second line loads the image with the function file_get_contents() by combining the base and the image file name. In the last line we use file_put_contents() to save the $fileData, we loaded just before, to the disk (using the local directory and the image file name).
$imageFileName = str_pad($imageNumber, 3, '0', STR_PAD_LEFT) . '.png';
$fileData = file_get_contents($baseUrl . $imageFileName);
file_put_contents($localDirectory . $imageFileName, $fileData);
The complete code should look like this:
<?php
$baseUrl = 'http://www.web.com/images/';
$localDirectory = 'downloaded_images/';
$maxImageNumber = 10;
for($imageNumber = 1; $imageNumber <= $maxImageNumber; $imageNumber++) {
$imageFileName = str_pad($imageNumber, 3, '0', STR_PAD_LEFT) . '.png';
$fileData = file_get_contents($baseUrl . $imageFileName);
file_put_contents($localDirectory . $imageFileName, $fileData);
}
In the unlikely event that this all should not work, there are a few things you can try
check that the $localDirectory exists and is writable.
if the file_get_contents() should not work, you can use curl instead
make sure the computer this code is executed on can access the remote server
Thank you so much but imagine that pics are in www.web.com/image_0001_big.png and www.web.com/image_002_big.png and so on... (last will be web.com/image_0200_big.png)
This doesn't work (i don't know why)
<?php
$baseUrl = 'http://www.web.com/images';
$localDirectory = 'downloaded_images/';
$maxImageNumber = 200;
$input='image_';
for($imageNumber = 001; $imageNumber <= $maxImageNumber; $imageNumber++) {
$imageFileName = str_pad($input, $imageNumber, 4, '_big', STR_PAD_LEFT) . '.png';
$fileData = file_get_contents($baseUrl . $imageFileName);
file_put_contents($localDirectory . $imageFileName, $fileData);
}
Thanks. You're amazing! Thanks for the help! I'm learning PHP and I'm a beginner yet:(
My error:
Warning: str_pad() expects at most 4 parameters, 5 given in C:\xampp\htdocs\auto.php on line 9
Warning: file_get_contents(http://www.web.com/images/.png): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in C:\xampp\htdocs\auto.php on line 10
I've found a semi-solution:_
<?php
$baseUrl = 'http://web.com/images';
$localDirectory = 'downloaded_images/';
$maxImageNumber = 400;
$input='image0';
$input2='big';
$extension ='.png';
for($imageNumber = 100; $imageNumber <= $maxImageNumber; $imageNumber++) {
$fileData = file_get_contents($baseUrl . $input . $imageNumber . $input2 . $extension);
file_put_contents($localDirectory . $imageNumber, $fileData);
}
?>
The problem is when... 0001 0009 0010 !! I want to tell php "hey, always 4 digits"

Copy Multiple Images From Remote Server

I am trying to copy multiple images from a remote host (using a URL) to my local box (using XAMPP on my local box to execute the script).
I am using copy(). When I go to execute the copy(), only the LAST image in the array is created. So, if I have 5 image links, only the 5th image gets created and nothing prior even gets a file created.
I have tried CURL and FOpen and then both create all of the files, but all of the files are blank except, again, the last file which is perfectly fine.
$txt_file = file_get_contents('urls_for_images.txt');
if(!empty($txt_file)){
$image_links = explode("\n", $txt_file);
$i = 1;
foreach($image_links as $image_link){
$file_info = pathinfo($image_link);
copy($image_link, 'images/00' . $i . '_original.' . $file_info['extension']);
$i++;
}
}
I am not sure where the problem is occurring, but it seems odd to me that it will copy the last image in the text file, but not any of the others.
Thanks for the help in advance!
The i variable never changes, therefore the code tries to copy a file with the same name over and over again and only the last file is saved.
Try modifying your code this way:
$txt_file = file_get_contents('urls_for_images.txt');
if(!empty($txt_file)){
$image_links = explode("\n", $txt_file);
$i = 1;
foreach($image_links as $image_link){
$file_info = pathinfo($image_link);
copy($image_link, 'images/00' . $i . '_original.' . $file_info['extension']);
$i++;
}
}
You'd be better off with just file(), which reads the file into an array automatically:
$files = file('urls_for_images.txt', FILE_IGNORE_NEW_LINES);
foreach($files as $remote_file) {
$local_file = ....;
copy($remote_file, $local_file);
}
It appears the problem is the text file which line endings are \r\n and you are exploding with only \n. The quickest way to fix this is either explode by \r\n; or trim with default parameters to remove \r from the end of each line.
foreach($image_links as $image_link){
$image_link = trim($image_link);
$file_info = pathinfo($image_link);
...
}
However, the cleanest way to do this is to use file function, which handles line endings automatically. I recommend you to use this approach.

upload images through php using unique file names

I am currently in the process of writing a mobile app with the help of phonegap. One of the few features that I would like this app to have is the ability to capture an image and upload it to a remote server...
I currently have the image capturing and uploading/emailing portion working fine with a compiled apk... but in my php, I am currently naming the images "image[insert random number from 10 to 20]... The problem here is that the numbers can be repeated and the images can be overwritten... I have read and thought about just using rand() and selecting a random number from 0 to getrandmax(), but i feel that I might have the same chance of a file overwriting... I need the image to be uploaded to the server with a unique name every-time, no matter what... so the php script would check to see what the server already has and write/upload the image with a unique name...
any ideas other than "rand()"?
I was also thinking about maybe naming each image... img + date + time + random 5 characters, which would include letters and numbers... so if an image were taken using the app at 4:37 am on March 20, 2013, the image would be named something like "img_03-20-13_4-37am_e4r29.jpg" when uploaded to the server... I think that might work... (unless theres a better way) but i am fairly new to php and wouldn't understand how to write something like that...
my php is as follows...
print_r($_FILES);
$new_image_name = "image".rand(10, 20).".jpg";
move_uploaded_file($_FILES["file"]["tmp_name"], "/home/virtual/domain.com/public_html/upload/".$new_image_name);
Any help is appreciated...
Thanks in advance!
Also, Please let me know if there is any further info I may be leaving out...
You may want to consider the PHP's uniqid() function.
This way the code you suggested would look like the following:
$new_image_name = 'image_' . date('Y-m-d-H-i-s') . '_' . uniqid() . '.jpg';
// do some checks to make sure the file you have is an image and if you can trust it
move_uploaded_file($_FILES["file"]["tmp_name"], "/home/virtual/domain.com/public_html/upload/".$new_image_name);
Also keep in mind that your server's random functions are not really random. Try random.org if you need something indeed random. Random random random.
UPD: In order to use random.org from within your code, you'll have to do some API requests to their servers. The documentation on that is available here: www.random.org/clients/http/.
The example of the call would be: random.org/integers/?num=1&min=1&max=1000000000&col=1&base=10&format=plain&rnd=new. Note that you can change the min, max and the other parameters, as described in the documentation.
In PHP you can do a GET request to a remote server using the file_get_contents() function, the cURL library, or even sockets. If you're using a shared hosting, the outgoing connections should be available and enabled for your account.
$random_int = file_get_contents('http://www.random.org/integers/?num=1&min=1&max=1000000000&col=1&base=10&format=plain&rnd=new');
var_dump($random_int);
You should use tempnam() to generate a unique file name:
// $baseDirectory Defines where the uploaded file will go to
// $prefix The first part of your file name, e.g. "image"
$destinationFileName = tempnam($baseDirectory, $prefix);
The extension of your new file should be done after moving the uploaded file, i.e.:
// Assuming $_FILES['file']['error'] == 0 (no errors)
if (move_uploaded_file($_FILES['file']['tmp_name'], $destinationFileName)) {
// use extension from uploaded file
$fileExtension = '.' . pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
// or fix the extension yourself
// $fileExtension = ".jpg";
rename($destinationFileName, $destinationFileName . $fileExtension);
} else {
// tempnam() created a new file, but moving the uploaded file failed
unlink($destinationFileName); // remove temporary file
}
Have you considered using md5_file ?
That way all of your files will have unique name and you would not have to worry about duplicate names. But please note that this will return same string if the contents are the same.
Also here is another method:
do {
$filename = DIR_UPLOAD_PATH . '/' . make_string(10) . '-' . make_string(10) . '-' . make_string(10) . '-' . make_string(10);
} while(is_file($filename));
return $filename;
/**
* Make random string
*
* #param integer $length
* #param string $allowed_chars
* #return string
*/
function make_string($length = 10, $allowed_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890') {
$allowed_chars_len = strlen($allowed_chars);
if($allowed_chars_len == 1) {
return str_pad('', $length, $allowed_chars);
} else {
$result = '';
while(strlen($result) < $length) {
$result .= substr($allowed_chars, rand(0, $allowed_chars_len), 1);
} // while
return $result;
} // if
} // make_string
Function will create a unique name before uploading image.
// Upload file with unique name
if ( ! function_exists('getUniqueFilename'))
{
function getUniqueFilename($file)
{
if(is_array($file) and $file['name'] != '')
{
// getting file extension
$fnarr = explode(".", $file['name']);
$file_extension = strtolower($fnarr[count($fnarr)-1]);
// getting unique file name
$file_name = substr(md5($file['name'].time()), 5, 15).".".$file_extension;
return $file_name;
} // ends for is_array check
else
{
return '';
} // else ends
} // ends
}

Categories