I'm having trouble to get the following code to upload large images. It works great with images less than 1000px by 1000px, but breaks on anything bigger. Any help/ideas greatly appreciated.
Note: I have tried increasing the '$memoryNeeded>=10000000' to '7700000000' but still no joy.
if (!$error && is_uploaded_file($_FILES['galleryFile']['tmp_name'])) {
$format = strtolower(substr(strrchr($_FILES['galleryFile']['name'],"."),1));
$str = strtolower(trim($_FILES['galleryFile']['name']));
$str = preg_replace('/[^a-z0-9-]/', '-', $str);
$str = preg_replace('/-+/', "-", $str);
$filename=$str.'.'.$format;
$uploadGallery=$origFileDir.$filename;
foreach ($allowedImgFormats as $key => $value) {
$value==$format ? $imgFormatOK='1' : NULL;
}
$imgFormatOK=='0' ? $error='You are attempting to upload an image with an invalid format!<br />Please only upload images with ".gif", ".jpg" or ".jpeg" extensions.' : NULL;
if (!$error && move_uploaded_file($_FILES['galleryFile']['tmp_name'], $uploadGallery)){
$galleryW='944'; $galleryH='733';
$galleryInfo = getimagesize($uploadGallery);
$memoryNeeded = Round(($galleryInfo[0] * $galleryInfo[1] * $galleryInfo['bits'] * $galleryInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
if ($memoryNeeded>=10000000) {
unlink($uploadGallery); $error='The chosen image is too large to process.<br />Please upload a smaller image (lower dimensions and/or resolution).';
} else {
list($wOrig, $hOrig) = getimagesize($uploadGallery);
$ratio_orig = $wOrig/$hOrig;
if ($wOrig > $galleryW) { $galleryW = $galleryH*$ratio_orig; $galleryH = $galleryW/$ratio_orig; } else { $galleryW=$wOrig; $galleryH=$hOrig; }
if ($galleryH > $galleryH) { $galleryH = $galleryW*$ratio_orig; $galleryW = $galleryH/$ratio_orig; }
$galleryP = imagecreatetruecolor($galleryW, $galleryH);
switch($format) {
case 'gif' : $thisGallery = imagecreatefromgif($uploadGallery); break;
case 'jpg' : $thisGallery = imagecreatefromjpeg($uploadGallery); break;
}
imagecopyresampled($galleryP, $thisGallery, 0, 0, 0, 0, $galleryW, $galleryH, $wOrig, $hOrig);
switch($format) {
case 'gif' : $createGallery=imagegif($galleryP, $galleryFileDir.$filename, 88); break;
case 'jpg' : $createGallery=imagejpeg($galleryP, $galleryFileDir.$filename, 88); break;
}
imagedestroy($galleryP); imagedestroy($thisGallery); unlink($uploadGallery);
if (!$createGallery) {
$error='The chosen image failed to transfer correctly.<br />Please try again, or attempt to upload an alternative image.';
file_exists($galleryFileDir.'/'.$filename) ? unlink($galleryFileDir.'/'.$filename) : NULL;
} else {
$_POST['imagename']=$filename;
mysql_query("INSERT INTO isgallery(imagename, assoc_object) VALUES('".$_POST['imagename']."', '".$_POST['id']."')");
}
}
} else {
!$error ? $error='The chosen image failed to upload correctly.<br />Please try again, or attempt to upload an alternative image.' : NULL;
file_exists($uploadGallery) ? unlink($uploadGallery) : NULL;
}
}
A 1000x1000 image requires at LEAST 3,000,000 bytes of memory if you're dealing with true color. and 4,000,000 if you're doing alpha transparency. Your $memoryNeeded variable is useless if it's set to something larger than PHP's memory_limit. It'll happily try to create an image and fail due to exceeded the limit.
You can check what the limit is with ini_get('memory_limit'), though you most likely won't be able to directly use this value for calculations without some massaging, as it'll likely return something like '32M' (32 megabyte limit), instead of 33554432.
Related
I'm trying to upload an Excel file using CodeIgniter. What I want to do is to just read the file without moving/uploading it in my upload path which is required in the configuration.
Yup, I can use the native PHP's $_FILES superglobal variable. But, I like to use the library because it gives me extra security to my app.
So.. how can I upload a file using CI's File Uploading class without being uploaded to my server?
$config['upload_path'] = './public/uploads/';
$config['allowed_types'] = 'xlsx|xls';
$this->load->library('upload', $config);
if(!$this->upload->do_upload('userfile'))
{
$this->output->set_output(array('result' => FALSE, 'message' => $this->upload->display_errors()))->_display();
exit(1);
}
else
{
$data = $this->upload->data();
// Let the model do his work!
$this->load->model('Userlist_Model');
$result = $this->Userlist_Model->extract_list($data);
$this->output->set_output($result)->_display();
}
Here's my solution: Just extend the Upload.php (CI_Upload) by creating MY_Upload inside the libraries folder. Copying the do_upload() method then remove the part where the upload starts:
MY_Upload.php
class MY_Upload extends CI_Upload
{
public function validate_file($field = 'userfile')
{
// Is $_FILES[$field] set? If not, no reason to continue.
if (isset($_FILES[$field]))
{
$_file = $_FILES[$field];
}
// Does the field name contain array notation?
elseif (($c = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $field, $matches)) > 1)
{
$_file = $_FILES;
for ($i = 0; $i < $c; $i++)
{
// We can't track numeric iterations, only full field names are accepted
if (($field = trim($matches[0][$i], '[]')) === '' OR ! isset($_file[$field]))
{
$_file = NULL;
break;
}
$_file = $_file[$field];
}
}
if ( ! isset($_file))
{
$this->set_error('upload_no_file_selected', 'debug');
return FALSE;
}
// Is the upload path valid?
if ( ! $this->validate_upload_path())
{
// errors will already be set by validate_upload_path() so just return FALSE
return FALSE;
}
// Was the file able to be uploaded? If not, determine the reason why.
if ( ! is_uploaded_file($_file['tmp_name']))
{
$error = isset($_file['error']) ? $_file['error'] : 4;
switch ($error)
{
case UPLOAD_ERR_INI_SIZE:
$this->set_error('upload_file_exceeds_limit', 'info');
break;
case UPLOAD_ERR_FORM_SIZE:
$this->set_error('upload_file_exceeds_form_limit', 'info');
break;
case UPLOAD_ERR_PARTIAL:
$this->set_error('upload_file_partial', 'debug');
break;
case UPLOAD_ERR_NO_FILE:
$this->set_error('upload_no_file_selected', 'debug');
break;
case UPLOAD_ERR_NO_TMP_DIR:
$this->set_error('upload_no_temp_directory', 'error');
break;
case UPLOAD_ERR_CANT_WRITE:
$this->set_error('upload_unable_to_write_file', 'error');
break;
case UPLOAD_ERR_EXTENSION:
$this->set_error('upload_stopped_by_extension', 'debug');
break;
default:
$this->set_error('upload_no_file_selected', 'debug');
break;
}
return FALSE;
}
// Set the uploaded data as class variables
$this->file_temp = $_file['tmp_name'];
$this->file_size = $_file['size'];
// Skip MIME type detection?
if ($this->detect_mime !== FALSE)
{
$this->_file_mime_type($_file);
}
$this->file_type = preg_replace('/^(.+?);.*$/', '\\1', $this->file_type);
$this->file_type = strtolower(trim(stripslashes($this->file_type), '"'));
$this->file_name = $this->_prep_filename($_file['name']);
$this->file_ext = $this->get_extension($this->file_name);
$this->client_name = $this->file_name;
// Is the file type allowed to be uploaded?
if ( ! $this->is_allowed_filetype())
{
$this->set_error('upload_invalid_filetype', 'debug');
return FALSE;
}
// if we're overriding, let's now make sure the new name and type is allowed
if ($this->_file_name_override !== '')
{
$this->file_name = $this->_prep_filename($this->_file_name_override);
// If no extension was provided in the file_name config item, use the uploaded one
if (strpos($this->_file_name_override, '.') === FALSE)
{
$this->file_name .= $this->file_ext;
}
else
{
// An extension was provided, let's have it!
$this->file_ext = $this->get_extension($this->_file_name_override);
}
if ( ! $this->is_allowed_filetype(TRUE))
{
$this->set_error('upload_invalid_filetype', 'debug');
return FALSE;
}
}
// Convert the file size to kilobytes
if ($this->file_size > 0)
{
$this->file_size = round($this->file_size/1024, 2);
}
// Is the file size within the allowed maximum?
if ( ! $this->is_allowed_filesize())
{
$this->set_error('upload_invalid_filesize', 'info');
return FALSE;
}
// Are the image dimensions within the allowed size?
// Note: This can fail if the server has an open_basedir restriction.
if ( ! $this->is_allowed_dimensions())
{
$this->set_error('upload_invalid_dimensions', 'info');
return FALSE;
}
// Sanitize the file name for security
$this->file_name = $this->_CI->security->sanitize_filename($this->file_name);
// Truncate the file name if it's too long
if ($this->max_filename > 0)
{
$this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);
}
// Remove white spaces in the name
if ($this->remove_spaces === TRUE)
{
$this->file_name = preg_replace('/\s+/', '_', $this->file_name);
}
if ($this->file_ext_tolower && ($ext_length = strlen($this->file_ext)))
{
// file_ext was previously lower-cased by a get_extension() call
$this->file_name = substr($this->file_name, 0, -$ext_length).$this->file_ext;
}
/*
* Validate the file name
* This function appends an number onto the end of
* the file if one with the same name already exists.
* If it returns false there was a problem.
*/
$this->orig_name = $this->file_name;
if (FALSE === ($this->file_name = $this->set_filename($this->upload_path, $this->file_name)))
{
return FALSE;
}
/*
* Run the file through the XSS hacking filter
* This helps prevent malicious code from being
* embedded within a file. Scripts can easily
* be disguised as images or other file types.
*/
if ($this->xss_clean && $this->do_xss_clean() === FALSE)
{
$this->set_error('upload_unable_to_write_file', 'error');
return FALSE;
}
/*
* Set the finalized image dimensions
* This sets the image width/height (assuming the
* file was an image). We use this information
* in the "data" function.
*/
$this->set_image_properties($this->upload_path.$this->file_name);
// Return true if the file passed the validation
return TRUE;
}
}
I have php javascript images upload problem. When I upload about 20kb, it is OK.
But when I upload over 500kb, it fails and displays the error shown below. My web site is hosted on godaddy. In my local development computer it works and runs smoothly. Do you have any ideas??
I have tried:
ini_set('post_max_size',52428800); // 50 MB
ini_set('upload_max_filesize',52428800) // 50 MB
But does not work.
//------ERROR on Web Pag----------
Request Entity Too Large
The requested resource /index.php/newPost/ does not allow request data with GET requests, or the amount of data provided in the request exceeds the capacity limit.
Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
//------------My code----------------------//
function uploadImages($input, $file)
{
if($input == null || $input == "")
{
return false;
}
$stringVal = $input;
$value = str_replace('data:image/png;base64,', '', $stringVal);
if ($this->check_base64_image($value) == false) {
return false;
}
$actualFile = base64_decode($value);
$img = imagecreatefromstring($actualFile);
$imgSize = getimagesize('data://application/octet-stream;base64,' . base64_encode($actualFile));
if ($img == false) {
return false;
}else
{
/*** maximum filesize allowed in bytes ***/
$max_file_length = 100000;
log_message('debug', 'PRE UPLOADING!!!!!!!!');
if (isset($img)){
log_message('debug', 'UPLOADING!!!!!!!!');
// check the file is less than the maximum file size
if($imgSize['0'] > $max_file_length || $imgSize['1'] > $max_file_length)
{
log_message('debug', 'size!!!!!!!!'.print_r($imgSize));
$messages = "File size exceeds $max_file_size limit";
return false;
}else if (file_exists($file)) {
return false;
}else
{
file_put_contents($file, $actualFile);
return true;
}
}
}
}
i'm having trouble with a script i modified, i used this class https://github.com/thenakos/compare-images since i wanted to check if in a determined folder there were only uniques photos.
public function scanDir($d)
{
/*function to find same photos in a dir*/
$tabImg = array();
$bitsList = array();
if(is_dir($d))
{
$dir = opendir($d);
$i = 0;
while($file = readdir($dir))
{
$path_parts = pathinfo($file);
if($file != '.' && $file != '..' && isset($path_parts['extension']) && $path_parts['extension'] == 'jpg')
{
$tabImg[] = $file;
$i++;
}
}
}
$i=0;
foreach($tabImg as $keyA => $imgA)
{
if($i<700) {
if(file_exists($d.$imgA))
{
$i1 = $this->createImage($d.$imgA);
if(!$i1){return false;}
$i1 = $this->resizeImage($i1,$d.$imgA);
imagefilter($i1, IMG_FILTER_GRAYSCALE);
$colorMean1 = $this->colorMeanValue($i1);
$bits1 = $this->bits($colorMean1);
$bitsList[$keyA] = $bits1;
imagedestroy($i1);
$i++;
}
}
}
$bitsListToCompare = $bitsList;
foreach($bitsList as $keyList => $valueList)
{
foreach($bitsListToCompare as $keyListToCompare => $valueListToCompare)
{
if($keyList != $keyListToCompare)
{
$hammeringDistance = 0;
for($b = 0;$b<64;$b++)
{
if($valueList[$b] != $valueListToCompare[$b])
{
$hammeringDistance++;
}
}
if($hammeringDistance < 5)
{
if(isset($arraySame[$tabImg[$keyList]])) $arraySame[$tabImg[$keyList]] = $arraySame[$a[$keyList]].';'.$tabImg[$keyListToCompare]; else $arraySame[$tabImg[$keyList]] = $tabImg[$keyListToCompare];
}
}
}
unset($bitsListToCompare[$keyList]);
}
return $arraySame;
}
i've added this function wich basically returns an array of duplicates images. This way it works fine, i'm checking 700 images. But if i don't limit the number of photos to check, i'm getting an error.
Warning: getimagesize() [function.getimagesize]: Read error!
This error is about the following function ( getimagesize )
private function mimeType($i)
{
/*returns array with mime type and if its jpg or png. Returns false if it isn't jpg or png*/
$mime = getimagesize($i);
$return = array($mime[0],$mime[1]);
switch ($mime['mime'])
{
case 'image/jpeg':
$return[] = 'jpg';
return $return;
case 'image/png':
$return[] = 'png';
return $return;
default:
return false;
}
}
i think it's something about the memory but i don't know how to make it work !
Thanks
As for memory - this line seems suspicious:
$i1 = $this->resizeImage($i1,$d.$imgA);
I don't know what's inside resizeImage() but it could be that it takes one GD resource as first argument, doesn't destroy it and returns another GD resource. Reference to the new resource replaces reference to the old resource that stays in memory. While resource without references to it will be eventually freed by garbage collector, it's not guaranteed it will do it in time.
So I would do:
$i2 = $this->resizeImage($i1,$d.$imgA);
imagedestroy($i1);
But there may be simpler reason. As PHP manual states on getimagesize():
If accessing the filename image is impossible getimagesize() will generate an error of level E_WARNING. On read error, getimagesize() will generate an error of level E_NOTICE.
Then in changelog:
5.2.3 Read errors generated by this function downgraded to E_NOTICE from E_WARNING.
So perhaps some photo has permission issue or something like that?
I am using getimagesize() to collect image information loaded remotely.
The problem is if the remote server takes too long on the request or the image doesn't exist and I get an error timeout. What can I do to prevent this, so that if it takes 15 seconds to load automatically make the request then return some code returning null $width, $height, and $type?
if($siteImage != "None"){
list($width, $height, $type) = getimagesize($siteImage);
if(!filter_var($siteImage, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)){
die("fillDiv('checkImage','<font color=\"red\">Image is not valid URL type.</font>');");
}elseif($width != "468" || $height != "60"){
die("fillDiv('checkImage','<font color=\"red\">Incorrect size.</font>');");
}elseif($type != "1" && $type != "2" && $type != "3"){
die("fillDiv('checkImage','<font color=\"red\">Incorrect image type. (.jpg .gif .png) only</font>');");
}else{
print("fillDiv('checkImage','');");
}
}
You have two options.
1 Use getimagesize but in two lines, and hide error messages. Check for a return value
$aSize = #getimagesize($url);
if ($aSize) {
// You have a return values
list($width, $height, $type) = $aSize;
} else {
// No return values
$width = 0; // etc
}
2 User cUrl to copy the file locally. You can control the timeous better with curl, also you can check if the file exists or is taking too long to download etc. Once copied locally, use getimagesize() on the local file. It will only then fail if the file is not a genuine image. Quick online example: http://www.weberdev.com/get_example.php3?ExampleID=4009
I am using following code and getting issue if there is an space in image name. And the issue is basically file is not loading at popwerpoint slide.
like:
$shape->setPath("C:/image/abc1.jpg"); // Working fine
$shape->setPath("C:/image/abc 1.jpg"); // Not working due to space in filename
I'm using the PHPPowerPoint class for generating powerpoint slides.
How do I get this to work?
EDIT
For the benefit of roine
public function setPath($pValue = '', $pVerifyFile = true) {
if ($pVerifyFile) {
if (file_exists($pValue)) {
$this->_path = $pValue;
if ($this->_width == 0 && $this->_height == 0) {
// Get width/height
list($this->_width, $this->_height) = getimagesize($pValue);
}
} else {
throw new Exception("File $pValue not found!");
}
} else {
$this->_path = $pValue;
}
return $this;
}
Try:
$shape->setPath("C:/image/abc%201.jpg");
If that works, you can use a simple string replace.
Try
$file_path = "C:/image/abc 1.jpg";
$clean_file_path = str_replace(" ", "%20", "$file_path");
$shape->setPath($clean_file_path);