Amazon S3 png files don't have transparency - php

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?

Related

s3 presigned url updating but cloudfront url not updating image

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.

Resizing an image with Intervention

Im trying to use Intervention with AWS S3, but the resize method is not working for me.
$img = Image::make($file)->rotate($rotate)->crop($width, $width, $x, $y);
$img->backup();
foreach(Config::get('img.image-sizes') as $_k => $_v){
$img->resize($_v['w'], $_v['h']);
$s3->queue($img, $name);
$img->reset();
}
The images upload fine to S3, but resize fails, I get all images the size of the original image
If I call save() on the image, the resize works, but I do not wish to save the image as I am uploading via S3, putting the $img as the body:
$this->commands[] = $this->s3->getCommand('PutObject', [
'Bucket' => env('AWS_BUCKET'),
'Key' => Config::get('img.image-path').$name,
'Body' => $img,
'ContentType' => $img->mime(),
'ACL' => 'public-read'
]);
To get this to work will I have to call save on each image first? If so is there a way to get this to play nice with S3, ideally I do not want to save them to my server first before sending them off to S3.
This is the code I used to get my uploaded images resized and saved to Amazon S3 using Laravel 5 and Intervention.
$imageFile = \Image::make($imageUpload)->resize(600, 600)->stream();
$imageFile = $imageFile->__toString();
$filename = 'myFileName.png';
$s3 = \Storage::disk('s3');
$s3_response = $s3->put('/'.$filename, $imageFile, 'public');

Generate a thumbnail of any upload file

I have a website where users upload document files. I want to display thumbnails of these documents. How can I display the first page of a document file as an image using codeigniter?
Below is the controller code:
public function do_upload()
{
require_once APPPATH . "php_include/authenticate.php";
$path = "uploads/file_attachment/";
if($_FILES['userfile']['name'] != ''){
$image = $_FILES['userfile']['name'];
$ext = pathinfo($image, PATHINFO_EXTENSION);
$filename = basename($image,'.'.$ext);
$filename = preg_replace("/[^a-zA-Z0-9]+/", "-", $filename);
$image = $filename.'.'.$ext;
move_uploaded_file($_FILES["userfile"]["tmp_name"],$path.$image);
$data = array(
'user_id' => $user_id,
'file' => $image,
);
$this->signupmodel->addfile($data);
}
}
This may be a bit of overkill for you but I described a bulletproof way to upload images. There are all kinds of ways where the extension (.jpg, .gif) does not match the image. Browsers have to do similar testing before rendering an image.
This code also chooses the most efficient image type to save it as and scales the image to multiple dimensions.
Stackoverflow: Scaling Images

How to upload image to AWS S3 in PHP from memory?

So I currently have an upload system working using AWS S3 to upload images.
Here's the code:
//Upload image to S3
$s3 = Aws\S3\S3Client::factory(array('key' => /*mykey*/, 'secret' => /*myskey*/,));
try {
$s3->putObject(array(
'Bucket' => "bucketname",
'Key' => $file_name,
'Body' => fopen(/*filelocation*/, 'r+')
));
} catch(Exception $e) {
//Error
}
This image can be a jpeg or png, and I want to convert it to a png before uploading. To do this I use:
//This is simplified, please don't warn about transparency, etc.
$image = imagecreatetruecolor($width, $height);
imagecopyresampled($image, $source, 0, 0, 0, 0, etc.);
So I have this $image object in memory.
I want to upload this to S3 without having to save it locally, upload it and then delete it locally; this extra step seems pointless. But I can't work out how to upload this $image object directly.
Any ideas how this would be done? I'd assumed fopen() would create an object of a similar type to imagecreatetruecolor(), but I've tried passing the $image object in and it doesn't work - whereas it does if I open an image locally with fopen().
You can capture the content of a GD image resource using output buffering:
ob_start();
imagepng($image);
$pngdata = ob_get_clean();

upload video from iphone device to server in php

I am working on the project which includes uploading image and video of user from iphone device. I am handling the backend with PHP. For uploading images I am getting the base64encode string and I have use following code to upload the image -
$str = $data['pictureurl']; // base64encode string
$newVar = base64_decode($str);
define('UPLOAD_DIR', 'userimages/');
$img = $str;
$date = strtotime(date("m-d-y H:i:s"));
$img = str_replace('data1:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data1 = base64_decode($img);
$file = UPLOAD_DIR . strtolower($data['firstName']).strtolower($data['lastName']). "_".$userId . '.png';
$totalpath = $path.$file;
#chmod('userimages/', 0777);
$success = file_put_contents($file, $data1);
From this code, image gets uploaded to the server in specified directory properly with .png extension. May I use the same code for uploading video making the file type .flv or .mov? I have tried it, but file gets placed in the folder with 0 bytes of data. What could be the problem? or is there any another solution to upload such file ?

Categories