s3 presigned url updating but cloudfront url not updating image - php

I am running into a problem with s3.
I allow the user to upload images on my website.
When an image is uploaded it stores in s3 and I use the [cloudfront] cdn to display the image.
But now i'm allowing the user to rotate the image. The user clicks the rotate button and the image rotates 90deg and stores back into s3. when I use s3 presigned url it shows that the image has rotated but when I use [cloudfront] url it still shows me the old image.
heres my code
$rotated = 0;
$fileName = $_POST['file'];
$originalFileName = $_POST['file'];
$keyName = basename($fileName);
//Creating a presigned URL
$cmd = $s3->getCommand('GetObject', [
'Bucket' => $bucketName,
'Key' => "uploads/" . $keyName,
]);
$request = $s3->createPresignedRequest($cmd, '+20 minutes');
// Get the actual presigned-url
$presignedUrl = (string)$request->getUri();
$img = basename($originalFileName);
// For this, I would generate a unqiue random string for the key name. But you can do whatever.
$keyName = 'uploads/' . $img;
$pathInS3 = 'https://<cloudfront_distribution_url>/' . $keyName;
$fileName = $pathInS3;
$degrees = 90;
$url = $fileName;
file_put_contents("../../../../uploads/" . $img, file_get_contents($url));
$source = imagecreatefromjpeg($fileName);
$rotate = imagerotate($source, $degrees, 0);
imagejpeg($rotate, "../../../../uploads/" . $img . "");
// Add it to S3
try {
// Uploaded:
$file = $originalFileName;
$s3->deleteObject(
array(
'Bucket' => $bucketName,
'Key' => $keyName
)
);
$s3->putObject(
array(
'Bucket' => $bucketName,
'Key' => $keyName,
'SourceFile' => "../../../../" . $file,
'StorageClass' => 'REDUCED_REDUNDANCY'
)
);
} catch (S3Exception $e) {
die('Error:' . $e->getMessage());
} catch (Exception $e) {
die('Error:' . $e->getMessage());
}
//here when I use presigned url it gives me back a url where the image has rotated but when using the $pathInS3 url which is the cloudfront url the image has not been rotated
echo $pathInS3;
on my cloudfront distribution I have created an invalidation.
All my images are stores in a folder called uploads/
so I created an invalidation for my folder uploads
which looks like this
uploads/
but this doesn't seem to work.
I then created an invalidation for everything
/*
also seems to not work.
Would love advice or help on how I can go about fixing this.
Thanks,
Arnav.

Related

Generate thumbnail from video using ffmpeg and add to mysql database

Im a noobie in php but still im trying :) Im making bulk video uploader/importer to database. Looking ideas how to extract thumbnails from videos on upload and add those thumbnails to mysql database for each video... :/ Im trying using ffmpeg, but i dont found the way how to implement it to my code...
<?php
// Database
include 'config/database.php';
if(isset($_POST['submit'])){
$url = "localhost/";
$uploadsDir = "uploads/";
$allowedExts = array("jpg", "jpeg", "gif", "png", "mp3", "mp4", "wma");
// Velidate if files exist
if (!empty(array_filter($_FILES['fileUpload']['name']))) {
// Loop through file items
foreach($_FILES['fileUpload']['name'] as $title=>$val){
// Get files upload path
$fileName = $_FILES['fileUpload']['name'][$title];
$tempLocation = $_FILES['fileUpload']['tmp_name'][$title];
$targetFilePath = $uploadsDir . $fileName;
$fileType = strtolower(pathinfo($targetFilePath, PATHINFO_EXTENSION));
$withOutExtension = pathinfo($fileName, PATHINFO_FILENAME);
$uploadDate = date('Y-m-d H:i:s');
$uploadOk = 1;
if(in_array($fileType, $allowedExts)){
if(move_uploaded_file($tempLocation, $targetFilePath)){
$sqlVal = $withOutExtension;
$sqlVal2 = $url . $uploadsDir . $fileName;
$sqlVal3 = null;
$randomID = rand(1000, 999999);
$sqlVal4 = ('<p><video controls="" src="/' . $sqlVal2 . '" width="640" height="360" class="note-video-clip"></video><br></p>');
$slug = str_replace(' ', '-', $withOutExtension);;
$file = $uploadsDir . $fileName;
$filesize = filesize($file); // bytes
$filesize = round($filesize / 1024 / 1024, 1);
} else {
$response = array(
"status" => "alert-danger",
"message" => "File coud not be uploaded."
);
}
} else {
$response = array(
"status" => "alert-danger",
"message" => "I want mp4 file."
);
}
// Add into MySQL database
if(!empty($sqlVal)) {
$insert = $conn->query("INSERT INTO applications (id, title, description, custom_description, details, image, slug, file_size, license, developer, url, buy_url, type, votes, screenshots, total_votes, counter, hits, category, platform, must_have, featured, pinned, editors_choice, created_at, updated_at) VALUES ('$randomID', '$sqlVal', 'Video .mp4 Live Wallpaper. Animated wallpaper is a cross between a screensaver and desktop wallpaper. Like a normal wallpaper, an animated wallpaper serves as the background on your desktop, which is visible to you only when your workspace is empty, i.e. no program windows block it from view.', '$sqlVal3', '$sqlVal4', '99999.jpg', '$slug', '$filesize MB', 'free', 'n/a', '$sqlVal2', '$sqlVal3', '1', '0.00', '', '0', '0', '1', '22', '6', '1', '1', '0', '1', '2021-11-11 16:55:36', '2021-11-11 16:55:36')");
if($insert) {
$response = array(
"status" => "alert-success",
"message" => "Files successfully uploaded."
);
} else {
$response = array(
"status" => "alert-danger",
"message" => "Files coudn't be uploaded due to database error."
);
}
}
}
} else {
// Error
$response = array(
"status" => "alert-danger",
"message" => "Please select a file to upload."
);
}
}
?>
Concerning the FFMpeg part, I think a good way to start is to actually use the PHP-FFMpeg library. The Basic Usage section in the documentation contains an example on how to generate a frame for a given video:
require 'vendor/autoload.php';
$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');
$video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10))
->save('frame.jpg');
A simplified process would be as follows:
The user uploads a video, after which the video gets moved to a different
directory.
Now you can use the snippet above, with the frame method to get a thumbnail for your video.
After the image saving is done, you just need to add it to your database.
If the thumbnails refer to the image column in your table, you can get away with just inserting the filename, frame.jpg (or even the complete filepath, /public/path/to/frame.jpg).
If the thumbnails refer to the screenshots column in your table, and you want to have multiple thumbnails for your video, then you should consider creating a new table with a one-to-many relationship (from your video/application to a new table, e.g. thumbnails)
Then when the user gets to a page where the image should be displayed, just select it from the table and display it with an <img> tag (with the public filepath).
I would also strongly recommend not to save the complete <video> tag into your database, but instead add it to the page where you actually want to show your video.
Example:
<?php
$result = $conn->query('SELECT ...');
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
?>
<video src="<?php echo $row['video-column-path']; ?>"</video>
<?php
}
} else {
?>
No videos here
<?php
}
$conn->close();
?>
Found solution, now need to understand how to import generated thumbnail url to database field for video...
// Velidate if files exist
if (!empty(array_filter($_FILES['fileUpload']['name']))) {
// Loop through file items
foreach($_FILES['fileUpload']['name'] as $title=>$val){
// Get files upload path
$fileName = $_FILES['fileUpload']['name'][$title];
$tempLocation = $_FILES['fileUpload']['tmp_name'][$title];
$targetFilePath = $uploadsDir . $fileName;
$fileType = strtolower(pathinfo($targetFilePath, PATHINFO_EXTENSION));
$withOutExtension = pathinfo($fileName, PATHINFO_FILENAME);
$uploadDate = date('Y-m-d H:i:s');
$uploadOk = 1;
$randomID = rand(1000, 999999);
//Get one thumbnail from the video
$ffmpeg = "C:\\ffmpeg\\bin\\ffmpeg";
//echo $ffmpeg;
$imageFile = 'pic/thumb_'.time().'_'.$randomID.'.jpg';
$size = "120x90";
$getFromSecond = 1;
echo $cmd = "$ffmpeg -i $tempLocation -an -ss $getFromSecond -s $size $imageFile";
echo "<br>";
if(!shell_exec($cmd)){
echo "Thumbnail Created!";
}else{
echo "Error creating Thumbnail";
}

Send file from HTML form to AWS S3 Bucket

I'm taking the file from a html form and then uploading it to an AWS S3 bucket.
The following code finds the path of the file on my computer and then uploads it to S3:
$bucketname = 'we-sign-files';
$file_path = '/Users/dripz/Desktop/wesign/uploads/5f31fc30410c17.68431957.jpg';
$key = basename($file_path);
try {
$s3->putObject([
'Bucket' => $bucketname,
'Key' => $key,
'Body' => fopen($file_path, 'r')
]);
} catch (Aws\S3\Exception\S3Exception $e) {
echo $e->getMessage();
}
What code should I put in the $file_path = variable to take the image from the users' computer and then upload to S3?
Use file_get_contents:
file_get_contents($_FILES['uploadedfileFormField']['tmp_name']);
and then you don't need: fopen.
Try-catch and error handling you have to take care of.
$bucketname = 'we-sign-files';
$fileName = $_FILES['uploadedfileFormField']['tmp_name'];
$file_path = file_get_contents($fileName);
$key = basename($fileName);
try {
$s3->putObject([
'Bucket' => $bucketname,
'Key' => $key,
'Body' => $file_path
]);
} catch (Aws\S3\Exception\S3Exception $e) {
echo $e->getMessage();
}

Upload File/Image with class Storage Laravel 5.2

First, I'm sorry for my bad English.
I want to upload a file/image from my driver to my project directory using class Storage. I want that every file/image will be uploaded/moved to my public/img directory. I use Form::file('img') on my views and on my post controller, I write this
$img = Input::file('img');
if ($img !== null) {
$filename = $img->getClientOriginalName();
Storage::disk('uploads')->put('filename', $filename);
$jenis->img = $filename;
}
and on my config/filesystem I write this
'uploads' => [
'driver' => 'local',
'root' => public_path() . '/img',
],
But, nothing happen on my public/img directory, no new file/image on there.
Can u help me whats wrong with my code?
and I hope u guys can help me with another good way on how to upload a file/image in laravel
Looks like your problem is you're not storing the file, you're referencing its name not its contents.
Try this:
Storage::disk('uploads') -> put($filename, file_get_contents($img -> getRealPath()));
In my filesystem file I configure my image directory in this way:
'uploads' => [
'driver' => 'local',
'root' => public_path("/img"),
],
I think that you can use your way but is another point.
To get the file from your view you should use File::get Laravel function:
$filename = $img->getClientOriginalName();
Storage::disk('uploads')->put($filename, \File::get($file));
With this would be enough, you save the file with the name of file uploaded in directory specify in filesystem.
if ($request->hasFile('original_pic')) {
$original_pic = $request->file('original_pic');
$file_extension=$original_pic>getClientOriginalExtension();
$filename = time() . '.' . $file_extension;
# upload original image
Storage::put('ArticlesImages/' . $filename, (string) file_get_contents($original_pic), 'public');
# croped image from request.
$image_parts = explode(";base64,", $request->input('article_image'));
$image_base64 = base64_decode($image_parts[1]);
Storage::put('ArticlesImages/croped/' . $filename, (string) $image_base64, 'public');
# get image from s3 or local storage.
$image_get = Storage::get('ArticlesImages/croped/' . $filename);
# resize 50 by 50 1x
$image_50_50 = Image::make($image_get)
->resize(340, 227)
->encode($file_extension, 80);
Storage::put('ArticlesImages/1x/' . $filename, (string) $image_50_50, 'public');
$file_url = Storage::url('ArticlesImages/croped/' . $filename);
return response()->json(['success' => true, 'filename' => $filename, 'file_url' => $file_url], 200);
}

Upload resized image to S3, using Yii

I want to upload a resized image to Amazon S3 bucket, using Yii framework, but to do it directly -- without uploading original (not resized) image to any folder, anywhere within Yii, website or server structure.
I have used ThumbsGen extension to create thumbnail of an image. The code works, if I upload file on my own server. But, if I upload the image to S3, then it will not create a thumbnail.
My code is look like this:
<?php
Yii::app()->setComponents(array('ThumbsGen' => array(
'class' => 'ext.ThumbsGen.ThumbsGen',
'thumbWidth' => Yii::t('constants', 'SECRETCODE_WIDTH'),
'thumbHeight' => Yii::t('constants', 'SECRETCODE_HEIGHT'),
'baseSourceDir' => Yii::app()->request->s3baseUrl.'/uploads/secretcode/original/',
'baseDestDir' => Yii::app()->request->s3baseUrl. '/uploads/secretcode/thumbs/',
'postFixThumbName' => null,
'nameImages' => array('*'),
'recreate' => false,
)));
class SecretCodeController extends MyController {
public function actionCreate() {
$model = new SecretCode;
$model->scenario = 'create';
if (isset($_POST['SecretCode'])) {
$model->attributes = $_POST['SecretCode'];
$temp = $model->promo_image = CUploadedFile::getInstance($model, 'promo_image');
if ($model->validate()) {
$rnd = rand(1, 1000);
$ext = $model->promo_image->extensionName;
$filename = 'secret_' . Yii::app()->user->app_id . '_' . time() . '_' . $rnd . '.' . $ext; $success = Yii::app()->s3->upload( $temp->tempName , 'uploads/secretcode/original/'.$filename);
if(!$success)
{
$model->addError('promo_image', Yii::t('constants', 'IMAGE_FAILURE'));
} else {
$model->promo_image = $filename; $model->promo_image = $filename;
$fullImgSource = #Yii::app()->s3->getObject(Yii::app()->params->s3bucket_name,"uploads/secretcode/original/".$filename);
list($width, $height, $type, $attr) = getimagesize($fullImgSource->headers['size']);
$dimensions = array();
$dimensions = CommonFunctions :: SetImageDimensions($width, $height,Yii::t('constants', 'SECRETCODE_WIDTH'), Yii::t('constants', 'SECRETCODE_HEIGHT'));
Yii::app()->ThumbsGen->thumbWidth = $dimensions['width'];
Yii::app()->ThumbsGen->thumbHeight = $dimensions['height'];
Yii::app()->ThumbsGen->createThumbnails();
}
if ($model->save()) {
Yii::app()->user->setFlash('success', Yii::t('constants', 'Secret Code')." ". Yii::t('constants', 'ADD_SUCCESS'));
$this->redirect(array('create'));
}
}
}
}
$this->render('create', array(
'model' => $model,
));
}
}
As a result, I'm getting a PHP warning:
getimagesize(42368) [<a href='function.getimagesize'>function.getimagesize</a>]: failed to open stream: No such file or directory
What am I doing wrong?
getimagesize — Get the size of an image
array getimagesize ( string $filename [, array &$imageinfo ] )
Your code:
list($width, $height, $type, $attr) = getimagesize($fullImgSource->headers['size']);
$fullImgSource->headers['size'] - I doubt that it stores the file path to image;
try this:
list($width, $height, $type, $attr) = $fullImgSource->headers['size'];
or
list($width, $height, $type, $attr) = getimagesize(/*path to image*/);
Can also read Transferring Files To and From Amazon S3

Amazon S3 png files don't have transparency

I'm not sure what I'm doing wrong, but PNG files uploaded to an S3 Amazon bucket show a white color instead of transparent, even though the local file does show transparency. Here is what I have:
$thumb = \PhpThumbFactory::create(
$content,
array(
'jpegQuality' => 100
),
true
);
$thumb->setFormat('PNG');
ob_start();
$thumb->show(true);
$content = ob_get_clean();
//This part is for testing purposes, I store the file locally to see that the transparency is there
$file = 'picture' . '-' . time() . '.png';
file_put_contents($file, $content); //The file created is an image which perfectly shows the transparent, as it should be
//The code below should upload the same file, but somehow it replaces transparency with a white color.
$S3 = new Zend_Service_Amazon_S3($myKey, $mySecret);
$response = $S3->putObject(
$bucket,
$content,
array(
Zend_Service_Amazon_S3::S3_CONTENT_TYPE_HEADER => 'image/png',
Zend_Service_Amazon_S3::S3_ACL_HEADER => Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ
)
);
Am I missing something when doing the upload? Is there anything that I should configure on the bucket?

Categories