Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
jQuery-File-Upload S3 PHP upload directly using AWS PHP SDK V2 (w/ optional Dropbox Chooser-selected files) https://github.com/blueimp/jQuery-File-Upload
<?php
use Aws\Common\Aws;
use Aws\S3\Exception\S3Exception;
// make sure the SDK is installed
// I've used Composer to autoload it: http://docs.aws.amazon.com/aws-sdk-php/guide/latest/installation.html
/*
* jQuery File Upload Plugin PHP Class 7.1.0
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
class UploadHandler
{
protected $options;
// PHP File Upload error message codes:
// http://php.net/manual/en/features.file-upload.errors.php
protected $error_messages = array(
1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
3 => 'The uploaded file was only partially uploaded',
4 => 'No file was uploaded',
6 => 'Missing a temporary folder',
7 => 'Failed to write file to disk',
8 => 'A PHP extension stopped the file upload',
'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini',
'max_file_size' => 'File is too big',
'min_file_size' => 'File is too small',
'accept_file_types' => 'Filetype not allowed',
'max_number_of_files' => 'Maximum number of files exceeded',
'max_width' => 'Image exceeds maximum width',
'min_width' => 'Image requires a minimum width',
'max_height' => 'Image exceeds maximum height',
'min_height' => 'Image requires a minimum height'
);
protected $image_objects = array();
function __construct($options = null, $initialize = true, $error_messages = null) {
$this->s3 = Aws::factory('/directory/to/AWS/keys/config.php')->get('s3')->registerStreamWrapper();
//Initialize the s3 client and "registerStreamWrapper()" allows using PHP's native file methods such as file_put_contents()
//http://docs.aws.amazon.com/aws-sdk-php/guide/latest/service-s3.html#amazon-s3-stream-wrapper
$this->prefix='somefolder/subfolder/'; //note there is no "folders" in S3 though you can prefix files with a string that resembles a file system.
$this->bucket="your-bucket";
//compatible with PHP frameworks such as Codeigniter by calling:
// $CI = & get_instance(); //get Codeigniter instance
//$this->form_validation= $CI->form_validation; //access some Codeigniter class and make a property of UploadHandler class
$this->options = array(
'script_url' => $this->get_full_url().'/',
'server_dir' => dirname($_SERVER['SCRIPT_FILENAME']).'/'.$this->prefix,
'upload_dir' =>'s3://'.$this->bucket.'/'.$this->prefix,
'server_url'=> $this->get_full_url().'/'.$this->prefix, //$user->publish->path,
'upload_url'=> "https://" . $this->bucket . ".s3.amazonaws.com/".$this->prefix,
'user_dirs' => false,
'mkdir_mode' => 0755,
'param_name' => 'files',
// Set the following option to 'POST', if your server does not support
// DELETE requests. This is a parameter sent to the client:
//'delete_type' => 'DELETE',
'delete_type' => 'POST', //note this is different from the default setting. "DELETE" was untested and "POST" works.
'access_control_allow_origin' => '*',
'access_control_allow_credentials' => false,
'access_control_allow_methods' => array(
'OPTIONS',
'HEAD',
'GET',
'POST',
'PUT',
'PATCH',
'DELETE'
),
'access_control_allow_headers' => array(
'Content-Type',
'Content-Range',
'Content-Disposition'
),
// Enable to provide file downloads via GET requests to the PHP script:
// 1. Set to 1 to download files via readfile method through PHP
// 2. Set to 2 to send a X-Sendfile header for lighttpd/Apache
// 3. Set to 3 to send a X-Accel-Redirect header for nginx
// If set to 2 or 3, adjust the upload_url option to the base path of
// the redirect parameter, e.g. '/files/'.
'download_via_php' => false,
// Read files in chunks to avoid memory limits when download_via_php
// is enabled, set to 0 to disable chunked reading of files:
'readfile_chunk_size' => 10 * 1024 * 1024, // 10 MiB
// Defines which files can be displayed inline when downloaded:
'inline_file_types' => '/\.(gif|jpe?g|png)$/i',
// Defines which files (based on their names) are accepted for upload:
'accept_file_types' => '/.+$/i',
// The php.ini settings upload_max_filesize and post_max_size
// take precedence over the following max_file_size setting:
'max_file_size' => null,
'min_file_size' => 1,
// The maximum number of files for the upload directory:
'max_number_of_files' => null,
// Defines which files are handled as image files:
'image_file_types' => '/\.(gif|jpe?g|png)$/i',
// Image resolution restrictions:
'max_width' => null,
'max_height' => null,
'min_width' => 1,
'min_height' => 1,
// Set the following option to false to enable resumable uploads:
'discard_aborted_uploads' => true,
// Set to 0 to use the GD library to scale and orient images,
// set to 1 to use imagick (if installed, falls back to GD),
// set to 2 to use the ImageMagick convert binary directly:
'image_library' => 1,
// Uncomment the following to define an array of resource limits
// for imagick:
/*
'imagick_resource_limits' => array(
imagick::RESOURCETYPE_MAP => 32,
imagick::RESOURCETYPE_MEMORY => 32
),
*/
// Command or path for to the ImageMagick convert binary:
'convert_bin' => 'convert',
// Uncomment the following to add parameters in front of each
// ImageMagick convert call (the limit constraints seem only
// to have an effect if put in front):
/*
'convert_params' => '-limit memory 32MiB -limit map 32MiB',
*/
// Command or path for to the ImageMagick identify binary:
'identify_bin' => 'identify',
'image_versions' => array(
// The empty image version key defines options for the original image:
'' => array(
// Automatically rotate images based on EXIF meta data:
'auto_orient' => true
),
// Uncomment the following to create medium sized images:
/*
'medium' => array(
'max_width' => 800,
'max_height' => 600
),
*/
'thumbnail' => array(
// Uncomment the following to use a defined directory for the thumbnails
// instead of a subdirectory based on the version identifier.
// Make sure that this directory doesn't allow execution of files if you
// don't pose any restrictions on the type of uploaded files, e.g. by
// copying the .htaccess file from the files directory for Apache:
//'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/thumb/',
//'upload_url' => $this->get_full_url().'/thumb/',
// Uncomment the following to force the max
// dimensions and e.g. create square thumbnails:
//'crop' => true,
'max_width' => 80,
'max_height' => 80
)
)
);
if ($options) {
$this->options = $options + $this->options;
}
if ($error_messages) {
$this->error_messages = $error_messages + $this->error_messages;
}
if ($initialize) {
$this->initialize();
}
}
protected function initialize() {
switch ($this->get_server_var('REQUEST_METHOD')) {
case 'OPTIONS':
case 'HEAD':
$this->head();
break;
case 'GET':
$this->get();
break;
case 'PATCH':
case 'PUT':
case 'POST':
$this->post();
break;
case 'DELETE':
$this->delete();
break;
default:
$this->header('HTTP/1.1 405 Method Not Allowed');
}
}
protected function get_full_url() {
$https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0;
return
($https ? 'https://' : 'http://').
(!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : '').
(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME'].
($https && $_SERVER['SERVER_PORT'] === 443 ||
$_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))).
substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/'));
}
protected function get_user_id() {
@session_start();
return session_id();
}
protected function get_user_path() {
if ($this->options['user_dirs']) {
return $this->get_user_id().'/';
}
return '';
}
protected function get_upload_path($file_name = null, $version = null) {
$file_name = $file_name ? $file_name : '';
if (empty($version)) {
$version_path = '';
} else {
$version_dir = @$this->options['image_versions'][$version]['upload_dir'];
if ($version_dir) {
return $version_dir.$this->get_user_path().$file_name;
}
$version_path = $version.'/'; //TRP 122713
//$version_path = $version; //TRP 122713
}
return $this->options['upload_dir'].$this->get_user_path()
.$version_path.$file_name;
}
protected function get_query_separator($url) {
return strpos($url, '?') === false ? '?' : '&';
}
protected function get_download_url($file_name, $version = null, $direct = false) {
if (!$direct && $this->options['download_via_php']) {
$url = $this->options['script_url']
.$this->get_query_separator($this->options['script_url'])
.'file='.rawurlencode($file_name);
if ($version) {
$url .= '&version='.rawurlencode($version);
}
return $url.'&download=1';
}
if (empty($version)) {
$version_path = '';
} else {
$version_url = @$this->options['image_versions'][$version]['upload_url'];
if ($version_url) {
return $version_url.$this->get_user_path().rawurlencode($file_name);
}
$version_path = rawurlencode($version).'/';
}
return $this->options['upload_url'].$this->get_user_path()
.$version_path.rawurlencode($file_name);
}
protected function set_additional_file_properties($file) {
$file->deleteUrl = $this->options['script_url']
.$this->get_query_separator($this->options['script_url'])
.$this->get_singular_param_name()
.'='.rawurlencode($file->name);
$file->deleteType = $this->options['delete_type'];
if ($file->deleteType !== 'DELETE') {
$file->deleteUrl .= '&_method=DELETE';
}
if ($this->options['access_control_allow_credentials']) {
$file->deleteWithCredentials = true;
}
}
// Fix for overflowing signed 32 bit integers,
// works for sizes up to 2^32-1 bytes (4 GiB - 1):
protected function fix_integer_overflow($size) {
if ($size < 0) {
$size += 2.0 * (PHP_INT_MAX + 1);
}
return $size;
}
protected function get_file_size($file_path, $clear_stat_cache = false) {
if ($clear_stat_cache) {
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
clearstatcache(true, $file_path);
} else {
clearstatcache();
}
}
return $this->fix_integer_overflow(filesize($file_path));
}
protected function is_valid_file_object($file_name) {
$file_path = $this->get_upload_path($file_name);
if (is_file($file_path) && $file_name[0] !== '.') {
return true;
}
return false;
}
protected function get_file_object($file_name) {
if ($this->is_valid_file_object($file_name)) {
$file = new stdClass();
$file->name = $file_name;
$file->size = $this->get_file_size(
$this->get_upload_path($file_name)
);
$file->url = $this->get_download_url($file->name);
foreach($this->options['image_versions'] as $version => $options) {
if (!empty($version)) {
if (is_file($this->get_upload_path($file_name, $version))) {
$file->{$version.'Url'} = $this->get_download_url(
$file->name,
$version
);
}
}
}
$this->set_additional_file_properties($file);
return $file;
}
return null;
}
protected function get_file_objects($iteration_method = 'get_file_object') {
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
//begin TRP 12/27/13
try{
//http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html#_listObjects
$result = $this->s3->listObjects(array(
// Bucket is required
'Bucket' => $this->bucket,
'Prefix' => $this->prefix
));
if(isset($result['Contents']) && count($result['Contents'])>0){
foreach($result['Contents'] as $obj){
if($obj['Key']!=$this->prefix && strpos($obj['Key'], '/thumbnail/')===false){ //if Key is a full file path and not just a "directory"
$a=pathinfo($obj['Key']);
$file_names_arr[]=$a['basename'];
}
}
}
}
catch (S3Exception $e) {
$data['status']=0;
$data['message']=$e;
//echo "There was an error uploading the file.\n";
}
if(!isset($file_names_arr)) $file_names_arr=array();
return array_values(array_filter(array_map(
array($this, $iteration_method),
$file_names_arr
)));
//end TRP 12/27/13
//return array(); //TRP 12/27/13
}
return array_values(array_filter(array_map(
array($this, $iteration_method),
scandir($upload_dir)
)));
}
protected function count_file_objects() {
return count($this->get_file_objects('is_valid_file_object'));
}
protected function get_error_message($error) {
return array_key_exists($error, $this->error_messages) ?
$this->error_messages[$error] : $error;
}
function get_config_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $this->fix_integer_overflow($val);
}
protected function validate($uploaded_file, $file, $error, $index) {
if ($error) {
$file->error = $this->get_error_message($error);
return false;
}
$content_length = $this->fix_integer_overflow(intval(
$this->get_server_var('CONTENT_LENGTH')
));
$post_max_size = $this->get_config_bytes(ini_get('post_max_size'));
if ($post_max_size && ($content_length > $post_max_size)) {
$file->error = $this->get_error_message('post_max_size');
return false;
}
if (!preg_match($this->options['accept_file_types'], $file->name)) {
$file->error = $this->get_error_message('accept_file_types');
return false;
}
if ($uploaded_file && is_uploaded_file($uploaded_file)) {
$file_size = $this->get_file_size($uploaded_file);
} else {
$file_size = $content_length;
}
if ($this->options['max_file_size'] && (
$file_size > $this->options['max_file_size'] ||
$file->size > $this->options['max_file_size'])
) {
$file->error = $this->get_error_message('max_file_size');
return false;
}
if ($this->options['min_file_size'] &&
$file_size < $this->options['min_file_size']) {
$file->error = $this->get_error_message('min_file_size');
return false;
}
if (is_int($this->options['max_number_of_files']) && (
$this->count_file_objects() >= $this->options['max_number_of_files'])
) {
$file->error = $this->get_error_message('max_number_of_files');
return false;
}
$max_width = @$this->options['max_width'];
$max_height = @$this->options['max_height'];
$min_width = @$this->options['min_width'];
$min_height = @$this->options['min_height'];
if (($max_width || $max_height || $min_width || $min_height)) {
list($img_width, $img_height) = $this->get_image_size($uploaded_file);
}
if (!empty($img_width)) {
if ($max_width && $img_width > $max_width) {
$file->error = $this->get_error_message('max_width');
return false;
}
if ($max_height && $img_height > $max_height) {
$file->error = $this->get_error_message('max_height');
return false;
}
if ($min_width && $img_width < $min_width) {
$file->error = $this->get_error_message('min_width');
return false;
}
if ($min_height && $img_height < $min_height) {
$file->error = $this->get_error_message('min_height');
return false;
}
}
return true;
}
protected function upcount_name_callback($matches) {
$index = isset($matches[1]) ? intval($matches[1]) + 1 : 1;
$ext = isset($matches[2]) ? $matches[2] : '';
return ' ('.$index.')'.$ext;
}
protected function upcount_name($name) {
return preg_replace_callback(
'/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/',
array($this, 'upcount_name_callback'),
$name,
1
);
}
protected function get_unique_filename($file_path, $name, $size, $type, $error,
$index, $content_range) {
while(is_dir($this->get_upload_path($name))) {
$name = $this->upcount_name($name);
}
// Keep an existing filename if this is part of a chunked upload:
$uploaded_bytes = $this->fix_integer_overflow(intval($content_range[1]));
while(is_file($this->get_upload_path($name))) {
if ($uploaded_bytes === $this->get_file_size(
$this->get_upload_path($name))) {
break;
}
$name = $this->upcount_name($name);
}
return $name;
}
protected function trim_file_name($file_path, $name, $size, $type, $error,
$index, $content_range) {
// Remove path information and dots around the filename, to prevent uploading
// into different directories or replacing hidden system files.
// Also remove control characters and spaces (\x00..\x20) around the filename:
$name = trim(basename(stripslashes($name)), ".\x00..\x20");
// Use a timestamp for empty filenames:
if (!$name) {
$name = str_replace('.', '-', microtime(true));
}
// Add missing file extension for known image types:
if (strpos($name, '.') === false &&
preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) {
$name .= '.'.$matches[1];
}
if (function_exists('exif_imagetype')) {
switch(exif_imagetype($file_path)){
case IMAGETYPE_JPEG:
$extensions = array('jpg', 'jpeg');
break;
case IMAGETYPE_PNG:
$extensions = array('png');
break;
case IMAGETYPE_GIF:
$extensions = array('gif');
break;
}
// Adjust incorrect image file extensions:
if (!empty($extensions)) {
$parts = explode('.', $name);
$extIndex = count($parts) - 1;
$ext = strtolower(@$parts[$extIndex]);
if (!in_array($ext, $extensions)) {
$parts[$extIndex] = $extensions[0];
$name = implode('.', $parts);
}
}
}
return $name;
}
protected function get_file_name($file_path, $name, $size, $type, $error,
$index, $content_range) {
return $this->get_unique_filename(
$file_path,
$this->trim_file_name($file_path, $name, $size, $type, $error,
$index, $content_range),
$size,
$type,
$error,
$index,
$content_range
);
}
protected function handle_form_data($file, $index) {
// Handle form data, e.g. $_REQUEST['description'][$index]
}
protected function get_scaled_image_file_paths($file_name, $version) {
$file_path = $this->get_upload_path($file_name);
if (!empty($version)) {
$version_dir = $this->get_upload_path(null, $version);
if (!is_dir($version_dir)) {
mkdir($version_dir, $this->options['mkdir_mode'], true);
}
//$new_file_path = $version_dir.'/'.$file_name; TRP 122713
$new_file_path = $version_dir.$file_name; //TRP 122713 b/c double slash
} else {
$new_file_path = $file_path;
}
return array($file_path, $new_file_path);
}
protected function gd_get_image_object($file_path, $func, $no_cache = false) {
if (empty($this->image_objects[$file_path]) || $no_cache) {
$this->gd_destroy_image_object($file_path);
$this->image_objects[$file_path] = $func($file_path);
}
return $this->image_objects[$file_path];
}
protected function gd_set_image_object($file_path, $image) {
$this->gd_destroy_image_object($file_path);
$this->image_objects[$file_path] = $image;
}
protected function gd_destroy_image_object($file_path) {
$image = @$this->image_objects[$file_path];
return $image && imagedestroy($image);
}
protected function gd_imageflip($image, $mode) {
if (function_exists('imageflip')) {
return imageflip($image, $mode);
}
$new_width = $src_width = imagesx($image);
$new_height = $src_height = imagesy($image);
$new_img = imagecreatetruecolor($new_width, $new_height);
$src_x = 0;
$src_y = 0;
switch ($mode) {
case '1': // flip on the horizontal axis
$src_y = $new_height - 1;
$src_height = -$new_height;
break;
case '2': // flip on the vertical axis
$src_x = $new_width - 1;
$src_width = -$new_width;
break;
case '3': // flip on both axes
$src_y = $new_height - 1;
$src_height = -$new_height;
$src_x = $new_width - 1;
$src_width = -$new_width;
break;
default:
return $image;
}
imagecopyresampled(
$new_img,
$image,
0,
0,
$src_x,
$src_y,
$new_width,
$new_height,
$src_width,
$src_height
);
return $new_img;
}
protected function gd_orient_image($file_path, $src_img) {
if (!function_exists('exif_read_data')) {
return false;
}
$exif = @exif_read_data($file_path);
if ($exif === false) {
return false;
}
$orientation = intval(@$exif['Orientation']);
if ($orientation < 2 || $orientation > 8) {
return false;
}
switch ($orientation) {
case 2:
$new_img = $this->gd_imageflip(
$src_img,
defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2
);
break;
case 3:
$new_img = imagerotate($src_img, 180, 0);
break;
case 4:
$new_img = $this->gd_imageflip(
$src_img,
defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1
);
break;
case 5:
$tmp_img = $this->gd_imageflip(
$src_img,
defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1
);
$new_img = imagerotate($tmp_img, 270, 0);
imagedestroy($tmp_img);
break;
case 6:
$new_img = imagerotate($src_img, 270, 0);
break;
case 7:
$tmp_img = $this->gd_imageflip(
$src_img,
defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2
);
$new_img = imagerotate($tmp_img, 270, 0);
imagedestroy($tmp_img);
break;
case 8:
$new_img = imagerotate($src_img, 90, 0);
break;
default:
return false;
}
$this->gd_set_image_object($file_path, $new_img);
return true;
}
protected function gd_create_scaled_image($file_name, $version, $options) {
if (!function_exists('imagecreatetruecolor')) {
error_log('Function not found: imagecreatetruecolor');
return false;
}
list($file_path, $new_file_path) =
$this->get_scaled_image_file_paths($file_name, $version);
$type = strtolower(substr(strrchr($file_name, '.'), 1));
switch ($type) {
case 'jpg':
case 'jpeg':
$src_func = 'imagecreatefromjpeg';
$write_func = 'imagejpeg';
$image_quality = isset($options['jpeg_quality']) ?
$options['jpeg_quality'] : 75;
break;
case 'gif':
$src_func = 'imagecreatefromgif';
$write_func = 'imagegif';
$image_quality = null;
break;
case 'png':
$src_func = 'imagecreatefrompng';
$write_func = 'imagepng';
$image_quality = isset($options['png_quality']) ?
$options['png_quality'] : 9;
break;
default:
return false;
}
$src_img = $this->gd_get_image_object(
$file_path,
$src_func,
!empty($options['no_cache'])
);
$image_oriented = false;
if (!empty($options['auto_orient']) && $this->gd_orient_image(
$file_path,
$src_img
)) {
$image_oriented = true;
$src_img = $this->gd_get_image_object(
$file_path,
$src_func
);
}
$max_width = $img_width = imagesx($src_img);
$max_height = $img_height = imagesy($src_img);
if (!empty($options['max_width'])) {
$max_width = $options['max_width'];
}
if (!empty($options['max_height'])) {
$max_height = $options['max_height'];
}
$scale = min(
$max_width / $img_width,
$max_height / $img_height
);
if ($scale >= 1) {
if ($image_oriented) {
return $write_func($src_img, $new_file_path, $image_quality);
}
if ($file_path !== $new_file_path) {
return copy($file_path, $new_file_path);
}
return true;
}
if (empty($options['crop'])) {
$new_width = $img_width * $scale;
$new_height = $img_height * $scale;
$dst_x = 0;
$dst_y = 0;
$new_img = imagecreatetruecolor($new_width, $new_height);
} else {
if (($img_width / $img_height) >= ($max_width / $max_height)) {
$new_width = $img_width / ($img_height / $max_height);
$new_height = $max_height;
} else {
$new_width = $max_width;
$new_height = $img_height / ($img_width / $max_width);
}
$dst_x = 0 - ($new_width - $max_width) / 2;
$dst_y = 0 - ($new_height - $max_height) / 2;
$new_img = imagecreatetruecolor($max_width, $max_height);
}
// Handle transparency in GIF and PNG images:
switch ($type) {
case 'gif':
case 'png':
imagecolortransparent($new_img, imagecolorallocate($new_img, 0, 0, 0));
case 'png':
imagealphablending($new_img, false);
imagesavealpha($new_img, true);
break;
}
$success = imagecopyresampled(
$new_img,
$src_img,
$dst_x,
$dst_y,
0,
0,
$new_width,
$new_height,
$img_width,
$img_height
) && $write_func($new_img, $new_file_path, $image_quality);
$this->gd_set_image_object($file_path, $new_img);
return $success;
}
protected function imagick_get_image_object($file_path, $no_cache = false) {
if (empty($this->image_objects[$file_path]) || $no_cache) {
$this->imagick_destroy_image_object($file_path);
$image = new Imagick();
if (!empty($this->options['imagick_resource_limits'])) {
foreach ($this->options['imagick_resource_limits'] as $type => $limit) {
$image->setResourceLimit($type, $limit);
}
}
$image->readImage($file_path);
$this->image_objects[$file_path] = $image;
}
return $this->image_objects[$file_path];
}
protected function imagick_set_image_object($file_path, $image) {
$this->imagick_destroy_image_object($file_path);
$this->image_objects[$file_path] = $image;
}
protected function imagick_destroy_image_object($file_path) {
$image = @$this->image_objects[$file_path];
return $image && $image->destroy();
}
protected function imagick_orient_image($image) {
$orientation = $image->getImageOrientation();
$background = new ImagickPixel('none');
switch ($orientation) {
case imagick::ORIENTATION_TOPRIGHT: // 2
$image->flopImage(); // horizontal flop around y-axis
break;
case imagick::ORIENTATION_BOTTOMRIGHT: // 3
$image->rotateImage($background, 180);
break;
case imagick::ORIENTATION_BOTTOMLEFT: // 4
$image->flipImage(); // vertical flip around x-axis
break;
case imagick::ORIENTATION_LEFTTOP: // 5
$image->flopImage(); // horizontal flop around y-axis
$image->rotateImage($background, 270);
break;
case imagick::ORIENTATION_RIGHTTOP: // 6
$image->rotateImage($background, 90);
break;
case imagick::ORIENTATION_RIGHTBOTTOM: // 7
$image->flipImage(); // vertical flip around x-axis
$image->rotateImage($background, 270);
break;
case imagick::ORIENTATION_LEFTBOTTOM: // 8
$image->rotateImage($background, 270);
break;
default:
return false;
}
$image->setImageOrientation(imagick::ORIENTATION_TOPLEFT); // 1
return true;
}
protected function imagick_create_scaled_image($file_name, $version, $options) {
list($file_path, $new_file_path) =
$this->get_scaled_image_file_paths($file_name, $version);
$image = $this->imagick_get_image_object(
$file_path,
!empty($options['no_cache'])
);
if ($image->getImageFormat() === 'GIF') {
// Handle animated GIFs:
$images = $image->coalesceImages();
foreach ($images as $frame) {
$image = $frame;
$this->imagick_set_image_object($file_name, $image);
break;
}
}
$image_oriented = false;
if (!empty($options['auto_orient'])) {
$image_oriented = $this->imagick_orient_image($image);
}
$new_width = $max_width = $img_width = $image->getImageWidth();
$new_height = $max_height = $img_height = $image->getImageHeight();
if (!empty($options['max_width'])) {
$new_width = $max_width = $options['max_width'];
}
if (!empty($options['max_height'])) {
$new_height = $max_height = $options['max_height'];
}
if (!($image_oriented || $max_width < $img_width || $max_height < $img_height)) {
if ($file_path !== $new_file_path) {
return copy($file_path, $new_file_path);
}
return true;
}
$crop = !empty($options['crop']);
if ($crop) {
$x = 0;
$y = 0;
if (($img_width / $img_height) >= ($max_width / $max_height)) {
$new_width = 0; // Enables proportional scaling based on max_height
$x = ($img_width / ($img_height / $max_height) - $max_width) / 2;
} else {
$new_height = 0; // Enables proportional scaling based on max_width
$y = ($img_height / ($img_width / $max_width) - $max_height) / 2;
}
}
$success = $image->resizeImage(
$new_width,
$new_height,
isset($options['filter']) ? $options['filter'] : imagick::FILTER_LANCZOS,
isset($options['blur']) ? $options['blur'] : 1,
$new_width && $new_height // fit image into constraints if not to be cropped
);
if ($success && $crop) {
$success = $image->cropImage(
$max_width,
$max_height,
$x,
$y
);
if ($success) {
$success = $image->setImagePage($max_width, $max_height, 0, 0);
}
}
$type = strtolower(substr(strrchr($file_name, '.'), 1));
switch ($type) {
case 'jpg':
case 'jpeg':
if (!empty($options['jpeg_quality'])) {
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality($options['jpeg_quality']);
}
break;
}
if (!empty($options['strip'])) {
$image->stripImage();
}
return $success && $image->writeImage($new_file_path);
}
protected function imagemagick_create_scaled_image($file_name, $version, $options) {
list($file_path, $new_file_path) =
$this->get_scaled_image_file_paths($file_name, $version);
$resize = @$options['max_width']
.(empty($options['max_height']) ? '' : 'x'.$options['max_height']);
if (!$resize && empty($options['auto_orient'])) {
if ($file_path !== $new_file_path) {
return copy($file_path, $new_file_path);
}
return true;
}
$cmd = $this->options['convert_bin'];
if (!empty($this->options['convert_params'])) {
$cmd .= ' '.$this->options['convert_params'];
}
$cmd .= ' '.escapeshellarg($file_path);
if (!empty($options['auto_orient'])) {
$cmd .= ' -auto-orient';
}
if ($resize) {
// Handle animated GIFs:
$cmd .= ' -coalesce';
if (empty($options['crop'])) {
$cmd .= ' -resize '.escapeshellarg($resize.'>');
} else {
$cmd .= ' -resize '.escapeshellarg($resize.'^');
$cmd .= ' -gravity center';
$cmd .= ' -crop '.escapeshellarg($resize.'+0+0');
}
// Make sure the page dimensions are correct (fixes offsets of animated GIFs):
$cmd .= ' +repage';
}
if (!empty($options['convert_params'])) {
$cmd .= ' '.$options['convert_params'];
}
$cmd .= ' '.escapeshellarg($new_file_path);
exec($cmd, $output, $error);
if ($error) {
error_log(implode('\n', $output));
return false;
}
return true;
}
protected function get_image_size($file_path) {
if ($this->options['image_library']) {
if (extension_loaded('imagick')) {
$image = new Imagick();
try {
if (@$image->pingImage($file_path)) {
$dimensions = array($image->getImageWidth(), $image->getImageHeight());
$image->destroy();
return $dimensions;
}
return false;
} catch (Exception $e) {
error_log($e->getMessage());
}
}
if ($this->options['image_library'] === 2) {
$cmd = $this->options['identify_bin'];
$cmd .= ' -ping '.escapeshellarg($file_path);
exec($cmd, $output, $error);
if (!$error && !empty($output)) {
// image.jpg JPEG 1920x1080 1920x1080+0+0 8-bit sRGB 465KB 0.000u 0:00.000
$infos = preg_split('/\s+/', $output[0]);
$dimensions = preg_split('/x/', $infos[2]);
return $dimensions;
}
return false;
}
}
if (!function_exists('getimagesize')) {
error_log('Function not found: getimagesize');
return false;
}
return @getimagesize($file_path);
}
protected function create_scaled_image($file_name, $version, $options) {
if ($this->options['image_library'] === 2) {
return $this->imagemagick_create_scaled_image($file_name, $version, $options);
}
if ($this->options['image_library'] && extension_loaded('imagick')) {
return $this->imagick_create_scaled_image($file_name, $version, $options);
}
return $this->gd_create_scaled_image($file_name, $version, $options);
}
protected function destroy_image_object($file_path) {
if ($this->options['image_library'] && extension_loaded('imagick')) {
return $this->imagick_destroy_image_object($file_path);
}
}
protected function is_valid_image_file($file_path) {
if (!preg_match($this->options['image_file_types'], $file_path)) {
return false;
}
if (function_exists('exif_imagetype')) {
return @exif_imagetype($file_path);
}
$image_info = $this->get_image_size($file_path);
return $image_info && $image_info[0] && $image_info[1];
}
protected function handle_image_file($file_path, $file) {
$failed_versions = array();
foreach($this->options['image_versions'] as $version => $options) {
if ($this->create_scaled_image($file->name, $version, $options)) {
if (!empty($version)) {
$file->{$version.'Url'} = $this->get_download_url(
$file->name,
$version
);
} else {
$file->size = $this->get_file_size($file_path, true);
}
} else {
$failed_versions[] = $version;
}
}
switch (count($failed_versions)) {
case 0:
break;
case 1:
$file->error = 'Failed to create scaled version: '
.$failed_versions[0];
break;
default:
$file->error = 'Failed to create scaled versions: '
.implode($failed_versions,', ');
}
// Free memory:
$this->destroy_image_object($file_path);
}
protected function handle_file_upload($uploaded_file, $name, $size, $type, $error,
$index = null, $content_range = null) {
$file = new stdClass();
$file->name = $this->get_file_name($uploaded_file, $name, $size, $type, $error,
$index, $content_range);
$file->size = $this->fix_integer_overflow(intval($size));
$file->type = $type;
if ($this->validate($uploaded_file, $file, $error, $index)) {
$this->handle_form_data($file, $index);
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
mkdir($upload_dir, $this->options['mkdir_mode'], true);
}
$file_path = $this->get_upload_path($file->name);
$append_file = $content_range && is_file($file_path) &&
$file->size > $this->get_file_size($file_path);
if ($uploaded_file && is_uploaded_file($uploaded_file) || (isset($_POST['fileSourceChooser']) && $_POST['fileSourceChooser']=='dropbox') ) {
// multipart/formdata uploads (POST method uploads)
//print_r($uploaded_file);
if ($append_file || (isset($_POST['fileSourceChooser']) && $_POST['fileSourceChooser']=='dropbox') ) {
file_put_contents(
$file_path,
fopen($uploaded_file, 'r'),
FILE_APPEND
);
}
else {
move_uploaded_file($uploaded_file, $file_path);
}
} else {
// Non-multipart uploads (PUT method support)
file_put_contents(
$file_path,
fopen('php://input', 'r'),
$append_file ? FILE_APPEND : 0
);
}
$file_size = $this->get_file_size($file_path, $append_file);
if ($file_size === $file->size) {
$file->url = $this->get_download_url($file->name);
if ($this->is_valid_image_file($file_path)) {
//$file_path='/private/var/tmp';
//$file_path=$uploaded_file; //TRP 122713
$this->handle_image_file($file_path, $file);
}
} else {
$file->size = $file_size;
if (!$content_range && $this->options['discard_aborted_uploads']) {
unlink($file_path);
$file->error = 'abort';
}
}
$this->set_additional_file_properties($file);
}
return $file;
}
protected function readfile($file_path) {
$file_size = $this->get_file_size($file_path);
$chunk_size = $this->options['readfile_chunk_size'];
if ($chunk_size && $file_size > $chunk_size) {
$handle = fopen($file_path, 'rb');
while (!feof($handle)) {
echo fread($handle, $chunk_size);
ob_flush();
flush();
}
fclose($handle);
return $file_size;
}
return readfile($file_path);
}
protected function body($str) {
echo $str;
}
protected function header($str) {
header($str);
}
protected function get_server_var($id) {
return isset($_SERVER[$id]) ? $_SERVER[$id] : '';
}
protected function generate_response($content, $print_response = true) {
if ($print_response) {
$json = json_encode($content);
$redirect = isset($_REQUEST['redirect']) ?
stripslashes($_REQUEST['redirect']) : null;
if ($redirect) {
$this->header('Location: '.sprintf($redirect, rawurlencode($json)));
return;
}
$this->head();
if ($this->get_server_var('HTTP_CONTENT_RANGE')) {
$files = isset($content[$this->options['param_name']]) ?
$content[$this->options['param_name']] : null;
if ($files && is_array($files) && is_object($files[0]) && $files[0]->size) {
$this->header('Range: 0-'.(
$this->fix_integer_overflow(intval($files[0]->size)) - 1
));
}
}
$this->body($json);
}
return $content;
}
protected function get_version_param() {
return isset($_GET['version']) ? basename(stripslashes($_GET['version'])) : null;
}
protected function get_singular_param_name() {
return substr($this->options['param_name'], 0, -1);
}
protected function get_file_name_param() {
$name = $this->get_singular_param_name();
return isset($_GET[$name]) ? basename(stripslashes($_GET[$name])) : null;
}
protected function get_file_names_params() {
$params = isset($_GET[$this->options['param_name']]) ?
$_GET[$this->options['param_name']] : array();
foreach ($params as $key => $value) {
$params[$key] = basename(stripslashes($value));
}
return $params;
}
protected function get_file_type($file_path) {
switch (strtolower(pathinfo($file_path, PATHINFO_EXTENSION))) {
case 'jpeg':
case 'jpg':
return 'image/jpeg';
case 'png':
return 'image/png';
case 'gif':
return 'image/gif';
default:
return '';
}
}
protected function download() {
switch ($this->options['download_via_php']) {
case 1:
$redirect_header = null;
break;
case 2:
$redirect_header = 'X-Sendfile';
break;
case 3:
$redirect_header = 'X-Accel-Redirect';
break;
default:
return $this->header('HTTP/1.1 403 Forbidden');
}
$file_name = $this->get_file_name_param();
if (!$this->is_valid_file_object($file_name)) {
return $this->header('HTTP/1.1 404 Not Found');
}
if ($redirect_header) {
return $this->header(
$redirect_header.': '.$this->get_download_url(
$file_name,
$this->get_version_param(),
true
)
);
}
$file_path = $this->get_upload_path($file_name, $this->get_version_param());
// Prevent browsers from MIME-sniffing the content-type:
$this->header('X-Content-Type-Options: nosniff');
if (!preg_match($this->options['inline_file_types'], $file_name)) {
$this->header('Content-Type: application/octet-stream');
$this->header('Content-Disposition: attachment; filename="'.$file_name.'"');
} else {
$this->header('Content-Type: '.$this->get_file_type($file_path));
$this->header('Content-Disposition: inline; filename="'.$file_name.'"');
}
$this->header('Content-Length: '.$this->get_file_size($file_path));
$this->header('Last-Modified: '.gmdate('D, d M Y H:i:s T', filemtime($file_path)));
$this->readfile($file_path);
}
protected function send_content_type_header() {
$this->header('Vary: Accept');
if (strpos($this->get_server_var('HTTP_ACCEPT'), 'application/json') !== false) {
$this->header('Content-type: application/json');
} else {
$this->header('Content-type: text/plain');
}
}
protected function send_access_control_headers() {
$this->header('Access-Control-Allow-Origin: '.$this->options['access_control_allow_origin']);
$this->header('Access-Control-Allow-Credentials: '
.($this->options['access_control_allow_credentials'] ? 'true' : 'false'));
$this->header('Access-Control-Allow-Methods: '
.implode(', ', $this->options['access_control_allow_methods']));
$this->header('Access-Control-Allow-Headers: '
.implode(', ', $this->options['access_control_allow_headers']));
}
public function head() {
$this->header('Pragma: no-cache');
$this->header('Cache-Control: no-store, no-cache, must-revalidate');
$this->header('Content-Disposition: inline; filename="files.json"');
// Prevent Internet Explorer from MIME-sniffing the content-type:
$this->header('X-Content-Type-Options: nosniff');
if ($this->options['access_control_allow_origin']) {
$this->send_access_control_headers();
}
$this->send_content_type_header();
}
public function get($print_response = true) {
if ($print_response && isset($_GET['download'])) {
return $this->download();
}
$file_name = $this->get_file_name_param();
if ($file_name) {
$response = array(
$this->get_singular_param_name() => $this->get_file_object($file_name)
);
} else {
$response = array(
$this->options['param_name'] => $this->get_file_objects()
);
}
return $this->generate_response($response, $print_response);
}
public function post($print_response = true) {
if (isset($_REQUEST['_method']) && $_REQUEST['_method'] === 'DELETE') {
return $this->delete($print_response);
}
$upload = isset($_FILES[$this->options['param_name']]) ?
$_FILES[$this->options['param_name']] : null;
// Parse the Content-Disposition header, if available:
$file_name = $this->get_server_var('HTTP_CONTENT_DISPOSITION') ?
rawurldecode(preg_replace(
'/(^[^"]+")|("$)/',
'',
$this->get_server_var('HTTP_CONTENT_DISPOSITION')
)) : null;
// Parse the Content-Range header, which has the following form:
// Content-Range: bytes 0-524287/2000000
$content_range = $this->get_server_var('HTTP_CONTENT_RANGE') ?
preg_split('/[^0-9]+/', $this->get_server_var('HTTP_CONTENT_RANGE')) : null;
$size = $content_range ? $content_range[3] : null;
$files = array();
if ($upload && is_array($upload['tmp_name'])) {
// param_name is an array identifier like "files[]",
// $_FILES is a multi-dimensional array:
foreach ($upload['tmp_name'] as $index => $value) {
$files[] = $this->handle_file_upload(
$upload['tmp_name'][$index],
$file_name ? $file_name : $upload['name'][$index],
$size ? $size : $upload['size'][$index],
$upload['type'][$index],
$upload['error'][$index],
$index,
$content_range
);
}
} else {
if( isset($_POST['fileSourceChooser']) && $_POST['fileSourceChooser']=='dropbox' ){
//http://justinvincent.com/page/1087/how-to-get-the-mime-type-of-a-remote-file-in-php-with-redirects
function get_url_mime_type($url){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_exec($ch);
return curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
}
$upload=$_POST['files']; ////if just a regular post
$upload['parse_url']=parse_url($upload['link']);
$upload['url']='https://dl.dropboxusercontent.com'.$upload['parse_url']['path'];
$files[] = $this->handle_file_upload(
$upload['url'],
$file_name ? $file_name : $upload['name'],
$size ? $size : $upload['bytes'],
get_url_mime_type($upload['url']),
"",
null, null,
$content_range
);
file_put_contents(
$this->options['upload_dir'].'thumbnail/'.$upload['name'],
fopen($upload['thumbnail'], 'r'),
FILE_APPEND //$append_file ? FILE_APPEND : 0
);
}
else{
// param_name is a single object identifier like "file",
// $_FILES is a one-dimensional array:
$files[] = $this->handle_file_upload(
isset($upload['tmp_name']) ? $upload['tmp_name'] : null,
$file_name ? $file_name : (isset($upload['name']) ?
$upload['name'] : null),
$size ? $size : (isset($upload['size']) ?
$upload['size'] : $this->get_server_var('CONTENT_LENGTH')),
isset($upload['type']) ?
$upload['type'] : $this->get_server_var('CONTENT_TYPE'),
isset($upload['error']) ? $upload['error'] : null,
null,
$content_range
);
}
}
return $this->generate_response(
array($this->options['param_name'] => $files),
$print_response
);
}
public function delete($print_response = true) {
$file_names = $this->get_file_names_params();
if (empty($file_names)) {
$file_names = array($this->get_file_name_param());
}
$response = array();
foreach($file_names as $file_name) {
$file_path = $this->get_upload_path($file_name);
$success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path);
if ($success) {
foreach($this->options['image_versions'] as $version => $options) {
if (!empty($version)) {
$file = $this->get_upload_path($file_name, $version);
if (is_file($file)) {
unlink($file);
}
}
}
}
$response[$file_name] = $success;
}
return $this->generate_response($response, $print_response);
}
}
@sachintaware

This comment has been minimized.

Copy link

sachintaware commented Jan 8, 2014

Great job Sir,I had modified the earlier uploadHandler file for S3 upload,but your is more modular as it adhres to the SDK.Forked it and if necessary will update if needed.
Thank you.Keep up the good job and All the best!

@designlook

This comment has been minimized.

Copy link

designlook commented Feb 24, 2014

Hi, great work! I am getting an error and was wondering if anyone might know... it writes the file fine to S3 but when it tries to create the thumbnail, it gets an error.

Fatal error: Uncaught exception 'ImagickException' with message 'WriteBlob Failed s3://xxxxx/somefolder/subfolder/thumbnail/Slide3.png' @ error/png.c/MagickPNGErrorHandler/1804' in //uploader/UploadHandlerS3.php on line 950 ( ! ) ImagickException: WriteBlob Faileds3://xxxx/somefolder/subfolder/thumbnail/Slide3.png' @ error/png.c/MagickPNGErrorHandler/1804 in /uploader/UploadHandlerS3.php on line 950

@designlook

This comment has been minimized.

Copy link

designlook commented Feb 24, 2014

The way this guy is doing it seems to work though... just not sure how to integrate it with this code.

http://stackoverflow.com/questions/189368/creating-an-image-without-storing-it-as-a-local-file

@designlook

This comment has been minimized.

Copy link

designlook commented Feb 24, 2014

OH... using GD instead of ImageMagick works in line #126. So I guess I'll just go that route. Thanks

@bijalbhavsar

This comment has been minimized.

Copy link

bijalbhavsar commented Mar 5, 2014

Hi Tim,

I am trying to implement above code with jquery file upload plugin. I have downloaded and include library from "http://docs.aws.amazon.com/aws-sdk-php/guide/latest/installation.html", but when i try to upload image it is showing me error like " Fatal error: Class 'Aws\Common\Aws' not found in E:\wamp\www\canvaspalette\jquery\file_upload\server\php\UploadHandlerS3.php on line 51".

In line no 51 code is like "$this->s3 = Aws::factory('AWS/keys/config.php')->get('s3')->registerStreamWrapper(); ". I searched in library, but no file like "keys/config.php" found in it. What will be to content of this file, is there anything i am missing.

Can you please help me to overcome from this issue.
Thanks in advance.

@bijalbhavsar

This comment has been minimized.

Copy link

bijalbhavsar commented Mar 24, 2014

I have resolved this issue using below code instead of creating config.php file.
$config = array(
'key' => '----------KEY-----------',
'secret' => '-----SECRET KEY---------------',
'region' => 'us-east-1'
);
$this->s3 = Aws::factory($config)->get('s3')->registerStreamWrapper();

@bijalbhavsar

This comment has been minimized.

Copy link

bijalbhavsar commented Mar 24, 2014

I am facing one more issue related to generate thumbnail using imagick. It is showing error like:

Fatal error: Uncaught exception 'ImagickException' with message 'unable to open image `s3://bucketname/uploads/2014/03/24/Wallpaper1 (1).jpg': No such file or directory @ error/blob.c/OpenBlob/2643' in /var/www/domain.com/public/2014/file_upload/server/php/UploadHandlerS3.php:991

Please help me to resolve above issue.
Thanks in advance

@tim-peterson

This comment has been minimized.

Copy link
Owner Author

tim-peterson commented May 19, 2014

@bijalbhavsar did you solve your problem?

@bhattkrishna19

This comment has been minimized.

Copy link

bhattkrishna19 commented Jul 2, 2014

Hey, How can I add ACL here?

@indicalabs

This comment has been minimized.

Copy link

indicalabs commented Jul 10, 2014

@tim-peterson
Thanks for the great work. I am able to upload successfully to s3 but the uploaded documents are 'private' by default, how to add ACL, policy, Signature.
One important question is that the documents are having the 'tmp_name' property, like below 'tmp_name' => [
'file' => '/private/var/tmp/phpQda26G'
]

that means the documents are comming to Webserver.
Is it not Direct Browser Upload? Is it same as PutObject?

@isocra

This comment has been minimized.

Copy link

isocra commented Jul 18, 2014

@tim-peterson
This is great, we've been adapting this to work with Yii and it works great. However we also have the same problem with ACL that @bijalbhavsar and @Venu85 have. When we upload files, they're private.

Somehow we need to specify ACL => 'public-read', but we can't see how to do this in an option or setting anywhere.

Thanks

@isocra

This comment has been minimized.

Copy link

isocra commented Jul 18, 2014

As an interim fix, this is what we ended up doing: just after the call to move_uploaded_file we added a call to putObjectAcl, as follows:

                else {
                    move_uploaded_file($uploaded_file, $file_path);
                    $key = $this->prefix . $name;
                    $this->s3->putObjectAcl(array(
                        'ACL' => 'public-read',
                        'Bucket' => $this->bucket,
                        'Key' => $key,
                    ));
                }

It's not very elegant, but at least it works.

@thond1st

This comment has been minimized.

Copy link

thond1st commented Sep 19, 2014

@tim-peterson,
Is it possible to upload files directly to S3 from Dropbox without downloading first on my local or on server first?
Thanks

@ghost

This comment has been minimized.

Copy link

ghost commented Sep 22, 2014

Thank you @isocra :) That did the trick!

@ghost

This comment has been minimized.

Copy link

ghost commented Sep 22, 2014

Improvement on @isocra's hack:

move_uploaded_file($uploaded_file, $file_path);
$key = $this->prefix . basename($file_path);
$this->s3->putObjectAcl(array(
  'ACL' => 'public-read',
  'Bucket' => $this->bucket,
  'Key' => $key,
));

I use basename($file_path) instead of $name to handle the cases when you upload a file with a repeated filename

@cassianotartari

This comment has been minimized.

Copy link

cassianotartari commented Sep 25, 2014

Does anybody get it working perfectly with image scale with all sizes?

This is what I got:

Warning: imagepng(): Unable to open 's3: ...

About the code line: ) && $write_func($new_img, $new_file_path, $image_quality);

@cassianotartari

This comment has been minimized.

Copy link

cassianotartari commented Sep 25, 2014

Finally get it working, using GD library I've changed the final of method gd_create_scaled_image to this:

$success = imagecopyresampled(
            $new_img,
            $src_img,
            $dst_x,
            $dst_y,
            0,
            0,
            $new_width,
            $new_height,
            $img_width,
            $img_height
        );

        ob_start();
        $result = $write_func($new_img, NULL, $image_quality);
        if ($result) {
             $contents = ob_get_contents();
             ob_end_clean();
        }
        $this->gd_set_image_object($file_path, $new_img);

         $context = stream_context_create(array(
            's3' => array(
                'ACL' => \AmazonS3::ACL_PUBLIC,
                'ContentType' => $this->get_file_type($file_path)
            )
        ));

        return file_put_contents($new_file_path, $contents, null, $context);

The $write_func functions (imagegif, imagepng, imagejpeg) doesn't work with stream wrapper so I've done that using a buffer and writing the result to server using file_put_contents

Hope it help somebody.

@bijalbhavsar, take a look.

@J-who

This comment has been minimized.

Copy link

J-who commented Dec 12, 2014

This script does not directly upload to s3 for me. Files are still being stored in the servers /tmp folder and then hitting upload limits from cloudflare.

@thond1st - Any luck with uploading directly to s3 from dropbox?

@schnabs

This comment has been minimized.

Copy link

schnabs commented Feb 17, 2015

This script is basically exactly what i'm looking for but i'm not really sure how the connect it to the "File Upload Plugin". This is basically a class definition but how to the hook this up to the AJAX request from the "File Upload Plugin"? Do I just create a class instance on the page that AJAX calls?

What am I suppose to pass in? $options = null, $initialize = true, $error_messages = null

options - Does this value matter? Looks like it will be overwritten anyways?
initalize - I would pass true here
error_messages - not sure what I should pass here

Also, I want to update my mysql database when files are upload / deleted. Should I just add this to the post() and delete() methods or is there a better way way? Should I update mysql db in the head() method to, but really sure what head() does

Thanks in advance!

@Ann12345

This comment has been minimized.

Copy link

Ann12345 commented Mar 15, 2015

Hi , I am trying to integrate this in my codeigniter application. How can i add aws in my server.Please help me.
Thanks in advance

@Ann12345

This comment has been minimized.

Copy link

Ann12345 commented Mar 15, 2015

HI in main.js which url i have to specify .Also form action points to index.php where the uploadhandler included is this correct?

@mitulkoradiya

This comment has been minimized.

Copy link

mitulkoradiya commented Jul 9, 2015

@Ann12345 did you get any answer? I am stuck with this problem. Please reply ASAP.
Thanks in advance

@brricey

This comment has been minimized.

Copy link

brricey commented Sep 29, 2015

Thanks for this. Trying to get this script to work however, the file upload but then the script fails.
The file does initially load to the profiles directory but then stops afterwards, please see error below


Warning: imagepng() [function.imagepng]: Unable to open 's3://bucket/profiles/thumbnail/-U_aTs7t (3).png' for writing: No such file or directory in /directory/Vendor/Blueimp/UploadHandlerS3.php on line 818

Warning:

@brricey

This comment has been minimized.

Copy link

brricey commented Sep 29, 2015

seems to be uploading now, but still not the thumbnail apparently its not registering file_put_contents() says i am unable to write despite the wrapper enabled in your script

ile_put_contents(https://asdfasdf.s3.amazonaws.com/profiles/thumbnail/8dff01eb-0148-4606-a83c-e6fc199d20ee-original.png) [function.file-put-contents]: failed to open stream: HTTP wrapper does not support writeable connections in /Applications/XAMPP/xamppfiles/htdocs/asdf/App/Application/Modules/Vendor/Blueimp/UploadHandlerS3.php on line 849

Warning

any help would be greate

@jlb30504

This comment has been minimized.

Copy link

jlb30504 commented Nov 9, 2015

This is working fine for me except performance seems low. I am uploading at about 300 kbps on a connection that provides almost 2 mbps for ftp to the server (no s3). The issue seems to be that transfers are limited to 6 concurrent session for some reason. I have tried increasing the concurrency in $config but it doesn't seem to impact throughput. Any thoughts on improving throughput?

@Peilin-Yang

This comment has been minimized.

Copy link

Peilin-Yang commented May 4, 2016

OH... using GD instead of ImageMagick works in line #126. So I guess I'll just go that route. Thanks

It works for me, thanks.

@appticaweb

This comment has been minimized.

Copy link

appticaweb commented Sep 14, 2016

Hi, i have a problem with integration in Yii2. I need to integrate your class with jQuery-File-Upload for upload directly to S3. Can you help me?

@bonillas

This comment has been minimized.

Copy link

bonillas commented Oct 14, 2016

I cant get it to display the images thumbnails, it is reading my directory from amazon s3 but it is returning the json array twice and I do not know why, I am getting this: "SyntaxError: Unexpected token { in JSON at position "

Any ideas?

@lauradean

This comment has been minimized.

Copy link

lauradean commented Dec 11, 2016

cassianotartari's fix worked for me, after I removed the context part

@DarkKnight1992

This comment has been minimized.

Copy link

DarkKnight1992 commented May 31, 2017

does any one know how to use this with bucketname.s3-accelerate.amazonaws.com – to access an acceleration-enabled bucket. To make uploads faster. Since it takes million years currently.

@mayank-mehrotra

This comment has been minimized.

Copy link

mayank-mehrotra commented Oct 10, 2018

Where to configure S3 bucket in which files need to be upload? Please, help me about this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.