I am working on a bulk upload project using excel sheet and using CakePHP 3.2 for writing application.
I have an excel sheet with a column to give image to be uploaded.
User have 3 choices to go with either
Upload images to a pre defined directory before bulk upload and give the name of the image in the cell and image will be automatically
selected from path.
Give the url of the image (http://website/path/image.jpg)
Give the path of the image if it is on local machine. Ex., C:\user\pictures\image.jpg if windows, and
/home/user/picture/image.jpg if linux
This is what I'm doing to save images
$p_image = $objWorksheet->getCellByColumnAndRow(30, $row)->getValue();
if (filter_var($p_image, FILTER_VALIDATE_URL)) {
// get image from url
$full_image_path = $p_image;
} else {
// get image from folder
$path = Configure::read('media.bulkUpload.pre.product');
// full path of the image from root directory
$full_image_path = $path . DS . $p_image;
}
$upload_path = Configure::read('media.upload') . DS . 'files' . DS;
// new name of image
$img_new_name = uniqid('img_').round(microtime(true) * 1000).rand(1,100000);
if ($full_image_path) {
// generate uuid directory name
$dir = Text::uuid();
// create new directory
mkdir($upload_path.$dir, 0777, true);
// save file
try {
$img = new \abeautifulsite\SimpleImage($full_image_path);
// save image of original size
$img->best_fit(850,1036)->save($upload_path.$dir.'/'.$img_new_name.'.jpg');
} catch(Exception $e) {
echo 'Error: '.$e->getMessage();
}
}
Image upload using url and pre ftp upload is working fine. But, how could I get image from the path of local system and then save them.
You can't do this without the users uploading the image themselves. You cannot retrieve a file from the client's filesystem from an external server where you run your php.
Related
I don't know if this has been asked before, please pardon in advance.
I created an image compression web app using the tinyPNG API, and it works as intended - that is users can upload an image file and it is compressed and saved in the server.
But then I create a download functionality for the user to download/save the compressed image.
On clicking the download link it throws up an error:
can’t find the file at http://localhost/var/www/html/imgtest/uploads/67403938_10219921906785196_7063388762713096192_n_1574687362.jpg.
Even though the compressed image is in the server.
Please help!!!
MY CODE:
require_once("vendor/autoload.php");
//makes PHP execute faster
set_time_limit(0);
//API key
\Tinify\setKey("API_KEY_HERE");
//Main code
if (isset($_POST['submit'])) {
//supported image formats.
$supported_image = array('image/jpg', 'image/jpeg', 'image/png');
foreach($_FILES['images']['name'] as $key=>$val){
$file_name = $_FILES['images']['name'][$key];
// get file extension
$ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
// get filename without extension
$filenamewithoutextension = pathinfo($file_name, PATHINFO_FILENAME);
if (in_array($_FILES['images']['type'][$key], $supported_image)) {
if (!file_exists(getcwd(). '/uploads')) {
$oldmask = umask(0);
mkdir(getcwd(). '/uploads', 0777, true);
umask($oldmask);
}
$filename_to_store = $filenamewithoutextension. '_' .time(). '.' .$ext;
move_uploaded_file($_FILES['images']['tmp_name'][$key], getcwd(). '/uploads/' .$filename_to_store);
$compress_file = getcwd(). '/uploads/' .$filename_to_store;
// optimize image using TinyPNG
try {
$source = \Tinify\fromFile(getcwd(). '/uploads/' .$filename_to_store);
$source->toFile(getcwd(). '/uploads/' .$filename_to_store);
//The code to show a modal for downloading the converted file.
} catch(Exception $e) {
echo $e->getMessage();
exit;
}
}
}
echo "<a href=".$compress_file." download>Download</a>";
}
?>```
The problem in your code is, that you create the link with $compress_file that contains absolute path to the file.
/var/www/html/imgtest/uploads/67403938_10219921906785196_7063388762713096192_n_1574687362.jpg
So when the link is clickend and the url is resolved in browser the result is
http://localhost/var/www/html/imgtest/uploads/67403938_10219921906785196_7063388762713096192_n_1574687362.jpg.
So if the localhost domain is pointed to /var/www/html/imgtest/ than the server is looking for the file in this path which doesn't exist:
/var/www/html/imgtest/var/www/html/imgtest/uploads/...
When you are generating the path to the compressed file you should put it's url into other variable where you wouldn't prepend the current directory.
$compress_file_url = '/uploads/' .$filename_to_store;
$compress_file = getcwd(). $compress_file_url;
Then you should use the $compress_file_url instead of $compress_file when creating a link
echo "<a href=\"$compress_file_url\" download>Download</a>";
This should work assuming your localhost domain is pointed to /var/www/html/imgtest. If your localhost domain is pointed to /var/www/html you might need to prepend $compress_file_url with /imgtest before it's used to create a link.
$compress_file_url = '/uploads/' .$filename_to_store;
$compress_file = getcwd(). $compress_file_url;
$compress_file_url = '/imgtest' . $compress_file_url;
I am using a file upload plugin in Vue to upload some image and pdf files through an API and it has an option to create a blob field when uploading the files.
The request sent to Laravel is as follows. I can access the blob from the browser by copying and pasting the URL on the browser.
On the Server side code, I am trying to save the file with the following code but the saved file is some corrupted 64byte file rather than the actual image. How would we store the blob as a normal file in the filesystem?
if ($request->has('files')) {
$files = $request->get('files');
$urls = [];
foreach ($files as $file) {
$filename = 'files/' . $file['name'];
// Upload File to s3
Storage::disk('s3')->put($filename, $file['blob']);
Storage::disk('s3')->setVisibility($filename, 'public');
$url = Storage::disk('s3')->url($filename);
$urls[] = $url;
}
return response()->json(['urls' => $urls]);
}
Try by replacing this:
Storage::disk('s3')->put($filename, $file['blob']);
with this:
Storage::disk('s3')->put($filename, base64_decode($file['blob']));
I am using Glide to deliver image content from one of my sites. This is working well and I have now built a file upload so that admins can upload images to the site for subsequent download.
Some of the images that admins will upload will be much larger than I need (or want the overhead of storing on the server), so I want to downsize them, preferably during the upload routine or failing that, just after they have been saved to their new location (storage/app/images)
So, I've been hacking around with intervention for instance without much success because of my poor understanding of the file names and paths available from getClientOriginalName/Extension etc.
Could anyone show me a pattern for this which would work well. Ideally I'd love to include something like I've seen on others' examples like...
$img = Image::make('foo.jpg')->resize(300, 200);
... in the correct place in my code
foreach($files as $file) {
$fileExtension = $file->getClientOriginalExtension();
$fileMimeType = $file->getMimeType();
if(in_array($fileExtension, $allowableExtensions)) {
if(in_array($fileMimeType, $allowableMimes)) {
array_push($dbFileList, $file->getClientOriginalName());
$newImage = '/images/' . $propertyCode . '/' . $file->getClientOriginalName();
Storage::put('/images/' . $propertyCode . '/' . $file->getClientOriginalName(), file_get_contents($file));
}else{
$errorMessage = 'At least one file was not an image, check your results...';
}
}else{
$errorMessage = 'At least one file was not an image, check your results...';
}
}
Update 1:
Storage::put('/images/' . $propertyCode . '/' . $file->getClientOriginalName(), file_get_contents($file));
$img = Image::make($file);
Storage::put('/images/new/' . $file->getClientOriginalName(), $img);
This updated code outputs the files to the /new directory and all looks fine, but the output files have 'zero bytes'. What am I missing?
Update 2: Final code
The final answer (after using the proper code provided by contributors) was that:
I had to move my app from virtual box on to the dev machine (iMac) to prevent extra confusion with paths
The path for the images must exist prior to making the ->save()
The path variable must be set in advance of the ->save()
I don't need the Storage::put at all, so the larger file never ends up on the server.
Then this final code started to work.
$path = storage_path('app/smallpics/')."/".$file->getClientOriginalName();
$img = Image::make($file)->resize(300,200)->save($path);
Much thanks to all of you. You make my Laravel learning curve a bit less terrifiying!!
You can use Intervention to manipulate your image (resize etc.) as
$new_image = Image::make($file)->resize(300,200)->save('/path/to/save');
The image upload and resize work flow is like:
Upload the image from tmp to your directory.
Make a copy of that image by setting the height, width, quality and save it in the same or some other directory.
Delete the original image.
So as per your code flow:
Storage::put('/images/' . $propertyCode . '/' . $file->getClientOriginalName(), file_get_contents($file));
after this code, put the image compress code and after that delete the original image.
you can use Intervention or just use imagemagick convert command line command for resize or convert.
Pay attention to comments :
public function saveUploadPic(Request $request)
{
$pic = $request->file('<NAME_OF_FILE_INPUT_IN_HTML_FORM>');
#check for upload correctly
if(!$pic->isValid())
{
throw new Exception("IMAGE NOT UPLOADED CORRECTLY");
}
#check for mime type and extention
$ext = $pic->getClientOriginalExtension();
$mime = $pic->getMimeType();
if(!in_array($mime, $allowedMimeTypeArray) || !in_array($ext, $allowedExtArray))
{
throw new Exception("This Image Not Support");
}
#check for size
$size = $pic->getClientSize() / 1024 / 1024;
if($size > $allowedSize)
{
throw new Exception("Size Of Image Is More Than Support Size");
}
########################YOU HAVE TWO OPTION HERE###################
#1- save image in a temporary location with random hash for name if u need orginal image for other process
#below code save image in <LARAVEL_APP_PATH>/storage/app/tmp/pics/
$hash = md5(date("YmdHis").rand(1,10000));
$pic->storeAs('tmp/pics', $hash.'.'.$ext);
#Then resize or convert it
$img = Image::make(storage_path('app/tmp/pics/'.$hash.'.'.$ext))->resize(300, 200);
#save new image whatever u want
$img->save('<PATH_TO_SAVE_IMAGE>');
#after u finish with orginal image delete it
Storage::delete(storage_path('app/tmp/pics/'.$hash.'.'.$ext);
#2- Or just use below for resize and save image witout need to save in temporary location
$img = Image::make($pic->getRealPath())->resize(300,200);
$img->save('<PATH_TO_SAVE_IMAGE>');
}
if you want to use convert see this link.
I created a blog where some users can upload images through the Wordpress dashboard. The site gets bogged down quickly because the original images are so big. Some users don't have the knowledge to resize the images themselves before uploading them, and I don't want to have to resize them manually.
Is there any way I can set a maximum width and height for uploaded images? I don't even want the original to remain on the website. I want the largest version of the image on the website to match the width and height restrictions I set.
add this code in your theme's functions.php it will replace the original image with the the re-sized version.
function replace_uploaded_image($image_data) {
// if there is no large image : return
if (!isset($image_data['sizes']['large'])) return $image_data;
// paths to the uploaded image and the large image
$upload_dir = wp_upload_dir();
$uploaded_image_location = $upload_dir['basedir'] . '/' .$image_data['file'];
$large_image_location = $upload_dir['path'] . '/'.$image_data['sizes']['large']['file'];
// delete the uploaded image
unlink($uploaded_image_location);
// rename the large image
rename($large_image_location,$uploaded_image_location);
// update image metadata and return them
$image_data['width'] = $image_data['sizes']['large']['width'];
$image_data['height'] = $image_data['sizes']['large']['height'];
unset($image_data['sizes']['large']);
return $image_data;
}
add_filter('wp_generate_attachment_metadata','replace_uploaded_image');
Article Source: http://goo.gl/nkszUn
Well why dont you create a new image size?
http://codex.wordpress.org/Function_Reference/add_image_size
And use that image on your templates.
This will work for new image uploads as well as older ones replacing user uploaded large images automatically with your defined Large size from admin panel's media settings:
add_filter('wp_generate_attachment_metadata','replace_uploaded_image');
function replace_uploaded_image($image_data) {
// if there is no large image : return
if (!isset($image_data['sizes']['large'])) return $image_data;
// paths to the uploaded image and the large image
$upload_dir = wp_upload_dir();
$uploaded_image_location = $upload_dir['basedir'] . '/' .$image_data['file'];
// $large_image_location = $upload_dir['path'] . '/'.$image_data['sizes']['large']['file']; // ** This only works for new image uploads - fixed for older images below.
$current_subdir = substr($image_data['file'],0,strrpos($image_data['file'],"/"));
$large_image_location = $upload_dir['basedir'] . '/'.$current_subdir.'/'.$image_data['sizes']['large']['file'];
// delete the uploaded image
unlink($uploaded_image_location);
// rename the large image
rename($large_image_location,$uploaded_image_location);
// update image metadata and return them
$image_data['width'] = $image_data['sizes']['large']['width'];
$image_data['height'] = $image_data['sizes']['large']['height'];
unset($image_data['sizes']['large']);
return $image_data;
}
In my current project I am using the plupload plugin with PHP and ImageMagick and its working fine - now my next task is too rename uploaded files in lowercase.
To rename these files I first store the uploaded image in a temporary folder with a ".temp" extension, than I move the file to a main folder and there I attempt to do a rename. The first time the function is executed, if there are no matching image then it will store it perfectly, but the second time through it doesn't work as well. The function should check for the existing file name and should store repeats with an incrementing index, i.e. as image_1.jpg, image_2.jpg, etc, but istead of doing that it just overwrites the image i.e. image.jpg.
Here is a snippet of my code:
$filename = $this->input->post('filename');
$root = $_SERVER["DOCUMENT_ROOT"]."/uploads/";
$source_image = $root.'temp/'.$filename;
$image_name = explode(".",$filename);
rename($source_image, $source_image. '.temp');
copy($source_image.'.temp', $root.$filename.'.temp');
unlink($source_image.'.temp');
$exp_temp_img_slash = explode(".",$filename);
$rename_img_a = strtolower($exp_temp_img_slash[0]);
$rename_img_b = $exp_temp_img_slash[1];
if (file_exists($root.$rename_img_a .".".$rename_img_b)) {
$count=1;
while (file_exists($root. $rename_img_a ."_".$count. ".".$rename_img_b)) {
$count++;
$rename_img = strtolower($rename_img_a . '_' . $count . ".".$rename_img_b);
}
$renamed_image = $_SERVER["DOCUMENT_ROOT"]."/uploads/".$rename_img;
rename($root.$filename.".temp",$renamed_image);
} else {
$rename_img = strtolower($rename_img_a .".".$rename_img_b);
$renamed_image = $_SERVER["DOCUMENT_ROOT"]."/uploads/".$rename_img;
rename($root.$filename.".temp",$renamed_image);
}
Any help will be appreciated, thanks.
shell_exec($imagemagick_folder."convert ".$from . $fileName." -resize ".$width."x".$height." -quality 95 ".$to.$fileName);
$imagemagick_folder is the folder where imagemagick is installed (ex. C:\imagemagick)
$from and $to are the the start and the destination folder
$width and $height are optional if you want to resize the image