Whit the follow code:
$file = fopen('php://input', 'r');
$temp = tmpfile();
$imageSize = stream_copy_to_stream($file, $temp);
$imageDimensions = getimagesize($file); // Error here
$imageInfos = pathinfo($_GET['selected-image']);
I get this error
getimagesize() expects parameter 1 to be string, resource given
Because $file is a resource of fopen. How I can have a resource and a string if I can't read php://input twice?
UPDATE
I have tried this:
$file = fopen('php://input', 'r');
$tempName = tempnam(sys_get_temp_dir(), '.upload');
$imageSize = fwrite(fopen($tempName, 'w+'), stream_get_contents($file));
$imageDimensions = getimagesize($tempName);
$imageInfos = pathinfo($_GET['selected-image']);
// Unlinks and other stuffs
The error:
Notice: getimagesize() [function.getimagesize]: Read error! in
Thanks!
Because getimagesize() only accepts string filenames, not resources, you will need to use tempnam() to create a temporary file with a name that you can pass to getimagesize().
$file = fopen('php://input', 'r');
$tempName = tempnam('/var/tmp', 'img_');
$temp = fopen($tempName, 'w');
$imageSize = stream_copy_to_stream($file, $temp);
fclose($temp);
$imageDimensions = getimagesize($tempName);
This assumes that the user running PHP has write and read permissions to the directory /var/tmp, but if it doesn't you can change to a directory that the user does have r/w permissions to.
Use tempnam() to generate your temp file, instead of tmpfile(). Then you have a file path which you can pass to getimagesize():
$file = fopen('php://input', 'r');
$tempname = tempnam('.', 'img');
$tempfile = fopen($tempname, 'w+');
$imageSize = stream_copy_to_stream($file, $tempfile);
$imageDimensions = getimagesize($tempname);
$imageInfos = pathinfo($_GET['selected-image']);
// At the end of the script, you need to remember to...
fclose($tempfile);
unlink($tempname);
Related
Trying to download files via the URL, rename from the .ADM extension to .txt
then put contents of each file into a single txt file
However its saying the fputs param 2 is a resource
The $logfile['name'] is the filename thats stored in the array
Heres my code
foreach($items as $logfile)
{
$getfile = $logfile['Download'];
$newfile = file_put_contents(str_replace('ADM','txt',$logfile['name']),
file_get_contents($getfile));
$name = str_replace('ADM','txt',$logfile['name']);
$newfile = $name;
$file = fopen($newfile, 'rb');
$output = fopen('tmp/test.txt', 'wb');
fputs($output, $file);
fclose($output);
fclose($file);
}
Its downloading each and renaming however its not moving the content & giving me this error
Warning: fputs() expects parameter 2 to be string, resource given in
The second parameter of fputs is the content of a file. Not a file resource.
Instead of
$file = fopen($newfile, 'rb');
You‘ll need to get the contents of the file
$content = file_get_contents($newfile);
Or, if you like to use fopen, you can use fread:
$file = fopen($newfile, 'rb');
$content = fread($fp, filesize($newfile));
Then you can put this content into another file:
fputs($output, $content);
I have following PHP code to create a folder and save an image into this generated folder. What works is the generation of the folder, but the associated image will not be inserted into the folder, so the folder is always empty:
$uid = $_POST['uid'];
$image = $_POST["image"];
$suffix = $db->createRandomID(); //function creates random numbers and stores in $suffix
$url = "http://XXX.XXX.XXX.XX/uploads_offer/";
$image_name = "img_offer_".$suffix."".$uid."_".date("Y-m-d-H-m-s").".jpg";
$path = $url."".$image_name; // path of saved image
// base64 encoded utf-8 string
$binary2 = base64_decode($image);
// binary, utf-8 bytes
header("Content-Type: bitmap; charset=utf-8");
$filepath = $image_name;
if (file_exists("../uploads_offer/".$uid)){
//$file = fopen("../uploads_offer/".$uid . $image_name, "wb");
$file = fopen("../uploads_offer".$uid.$image_name, "wb");
fwrite($file, $binary2);
fclose($file);
}else{
$result8 = mkdir("../uploads_offer/".$uid, 0755);
$file = fopen("../uploads_offer".$uid.$image_name, "wb");
fwrite($file, $binary2);
fclose($file);
}
You are missing slashes (/) in your fopen() calls:
$file = fopen("../uploads_offer/".$uid."/".$image_name, "wb");
I'm using Valum's file uploader to upload images with AJAX. This script submits the file to my server in a way that I don't fully understand, so it's probably best to explain by showing my server-side code:
$pathToFile = $path . $filename;
//Here I get a file not found error, because the file is not yet at this address
getimagesize($pathToFile);
$input = fopen('php://input', 'r');
$temp = tmpfile();
$realSize = stream_copy_to_stream($input, $temp);
//Here I get a string expected, resource given error
getimagesize($input);
fclose($input);
$target = fopen($pathToFile, 'w');
fseek($temp, 0, SEEK_SET);
//Here I get a file not found error, because the image is not at the $target yet
getimagesize($pathToFile);
stream_copy_to_stream($temp, $target);
fclose($target);
//Here it works, because the image is at the desired location so I'm able to access it with $pathToFile. However, the (potentially) malicious file is already in my server.
getimagesize($pathToFile);
The problem is that I want to perform some file validation here, using getimagesize(). getimagesize only supports a string, and I only have resources available, which result in the error: getimagesize expects a string, resource given.
It does work when I perform getimagesize($pathTofile) at the end of the script, but then the image is already uploaded and the damage could already have been done. Doing this and performing the check afterwards and then maybe deleting te file seems like bad practice to me.
The only thing thats in $_REQUEST is the filename, which i use for the var $pathToFile. $_FILES is empty.
How can I perform file validation on streams?
EDIT:
the solution is to first place the file in a temporary directory, and perform the validation on the temporary file before copying it to the destination directory.
// Store the file in tmp dir, to validate it before storing it in destination dir
$input = fopen('php://input', 'r');
$tmpPath = tempnam(sys_get_temp_dir(), 'upl'); // upl is 3-letter prefix for upload
$tmpStream = fopen($tmpPath, 'w'); // For writing it to tmp dir
stream_copy_to_stream($input, $tmpStream);
fclose($input);
fclose($tmpStream);
// Store the file in destination dir, after validation
$pathToFile = $path . $filename;
$destination = fopen($pathToFile, 'w');
$tmpStream = fopen($tmpPath, 'r'); // For reading it from tmp dir
stream_copy_to_stream($tmpStream, $destination);
fclose($destination);
fclose($tmpStream);
PHP 5.4 now supports getimagesizefromstring
See the docs:
http://php.net/manual/pt_BR/function.getimagesizefromstring.php
You could try:
$input = fopen('php://input', 'r');
$string = stream_get_contents($input);
fclose($input);
getimagesizefromstring($string);
Instead of using tmpfile() you could make use of tempnam() and sys_get_temp_dir() to create a temporary path.
Then use fopen() to get a handle to it, copy over the stream.
Then you've got a string and a handle for the operations you need to do.
//Copy PHP's input stream data into a temporary file
$inputStream = fopen('php://input', 'r');
$tempDir = sys_get_temp_dir();
$tempExtension = '.upload';
$tempFile = tempnam($tempDir, $tempExtension);
$tempStream = fopen($tempFile, "w");
$realSize = stream_copy_to_stream($inputStream, $tempStream);
fclose($tempStream);
getimagesize($tempFile);
I would like to download a zip archive and unzip it in memory using PHP.
This is what I have today (and it's just too much file-handling for me :) ):
// download the data file from the real page
copy("http://www.curriculummagic.com/AdvancedBalloons.kmz", "./data/zip.kmz");
// unzip it
$zip = new ZipArchive;
$res = $zip->open('./data/zip.kmz');
if ($res === TRUE) {
$zip->extractTo('./data');
$zip->close();
}
// use the unzipped files...
Warning: This cannot be done in memory — ZipArchive cannot work with "memory mapped files".
You can obtain the data of a file inside a zip-file into a variable (memory) with file_get_contentsDocs as it supports the zip:// Stream wrapper Docs:
$zipFile = './data/zip.kmz'; # path of zip-file
$fileInZip = 'test.txt'; # name the file to obtain
# read the file's data:
$path = sprintf('zip://%s#%s', $zipFile, $fileInZip);
$fileData = file_get_contents($path);
You can only access local files with zip:// or via ZipArchive. For that you can first copy the contents to a temporary file and work with it:
$zip = 'http://www.curriculummagic.com/AdvancedBalloons.kmz';
$file = 'doc.kml';
$ext = pathinfo($zip, PATHINFO_EXTENSION);
$temp = tempnam(sys_get_temp_dir(), $ext);
copy($zip, $temp);
$data = file_get_contents("zip://$temp#$file");
unlink($temp);
As easy as:
$zipFile = "test.zip";
$fileInsideZip = "somefile.txt";
$content = file_get_contents("zip://$zipFile#$fileInsideZip");
Old subject but still relevant since I asked myself the same question, without finding an answer.
I ended up writing this function which returns an array containing the name of each file contained in the archive, as well as the decompressed contents of that file:
function GetZipContent(String $body_containing_zip_file) {
$sectors = explode("\x50\x4b\x01\x02", $data);
array_pop($sectors);
$files = explode("\x50\x4b\x03\x04", implode("\x50\x4b\x01\x02", $sectors));
array_shift($files);
$result = array();
foreach($files as $file) {
$header = unpack("vversion/vflag/vmethod/vmodification_time/vmodification_date/Vcrc/Vcompressed_size/Vuncompressed_size/vfilename_length/vextrafield_length", $file);
array_push($result, [
'filename' => substr($file, 26, $header['filename_length']),
'content' => gzinflate(substr($file, 26 + $header['filename_length'], -12))
]);
}
return $result;
}
Hope this is useful ...
You can get a stream to a file inside the zip and extract it into a variable:
$fp = $zip->getStream('test.txt');
if(!$fp) exit("failed\n");
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
If you can use system calls, the simplest way should look like this (bzip2 case). You just use stdout.
$out=shell_exec('bzip2 -dkc '.$zip);
I am trying to read a raw input stream from php using php://input. This works for most files, however, files over 4MB are being ignored in the upload. I have set post_max_size and upload_max_size to 20M each thinking it would solve my problem, but it didn't. Is there another php.ini setting that needs to be configured or do I need to do chunking of some sort? If so, how would I go about doing that? Here is the upload.php code:
$fileName = $_SERVER['HTTP_X_FILE_NAME'];
$contentLength = $_SERVER['CONTENT_LENGTH'];
file_put_contents('uploads/' . $fileName, file_get_contents("php://input"));
Try stream_copy_to_stream, which directly pumps the content of the input into the file without copying it all into memory first:
$input = fopen('php://input', 'rb');
$file = fopen($filename, 'wb');
stream_copy_to_stream($input, $file);
fclose($input);
fclose($file);
Alternative:
$input = fopen('php://input', 'rb');
$file = fopen($filename, 'wb');
while (!feof($input)) {
fwrite($file, fread($input, 102400));
}
fclose($input);
fclose($file);