Platform: Windows 10 & IIS, PHP 5.6
$base_dir = dirname(__DIR__);
$export_dir = 'export/';
if (!file_exists($export_dir)) {
mkdir($export_dir, 0777, true);
}
$date = date_create(date());
$file_name = date_format($date,"Ymd").".txt";
if (file_exists($export_dir.$file_name)) {
unlink($export_dir . $file_name);
}
$file = fopen($export_dir . $file_name, "w");
fclose($file);
The above code seems perfect with BLANK file output, however, when open the blank file, it contains a BLANK line inside and file size is not 0 kb.
I also tried "wt" or "wb" but output is the same.
What can I do to make sure create the .txt file is 0 kb?
Related
I've got a ZIP file sitting on my server. I want to unzip it and then save the completely file contents into just one variable.
I do NOT want to save the unzipped file on my server or on a visitor's computer. I just need all of the contents of that zipped file stored in a variable that I can play around with and eventually show on the screen. Every other solution I've found for this problem includes resaving the file in unzipped form.
How can I do this with get_file_contents, or any other function?
You can simply find out the file names within the ZIP Archive with PHPs ZipArchive for example. try this (have not tested it but you should be able to get it to work) :
$za = new ZipArchive();
$za->open('archive.zip');
$fileContents = array();
for( $i = 0; $i < $za->numFiles; $i++ ) {
$stat = $za->statIndex( $i );
$fp = $z->getStream($stat['name']);
if(!$fp) exit("failed\n");
$contents = '';
while (!feof($fp)) {
$contents .= fread($fp, 1000);
}
fclose($fp);
$fileContents[$stat['name']] = $contents;
}
Once you know the names of the files within the Zip you can also use something like this:
$path = sprintf('zip://%s#%s', $zipArchive, $fileNameInZipArchive);
$fileData = file_get_contents($path);
For an upload file type checking , I have implemented:
$_FILES["file"]["type"][$i] == 'application/pdf'
however, this checking will not work on the case I changed the extension name.
So , after some research, I have tried
$finfo = new finfo();
$fileMimeType = $finfo->file($_FILES["file"]["name"][$i] );
OR:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$fileMimeType = finfo_file($finfo,$_FILES["file"]["name"][$i])
however, $fileMimeType echo nothing.
How to fix the problem? thanks
Read the first 4 bytes of the file and check that they match %PDF.
$filename = "pdffile";
$handle = fopen($filename, "r");
$header = fread($handle, 4);
fclose($handle);
Check $header against %PDF
I guess the problem is using:
$_FILES["my_file"]["name"]
as it only contains the name of the uploaded file. If you want to check the file before moving it using move_uploaded_file you can refer to the temp file using:
$_FILES["my_file"]["tmp_name"]
if you read the file using fread you need to have a dictionary of all the file header type definitions. If you want to use the file shell command
$out = exec("file 'R-intro.pdf' | cut -d: -f2 | cut -d, -f1");
if (trim($out) == "PDF document") {
echo "1";
}
To further expand on how to replace the constant file name with a uploaded file refer below.
$out = exec("file '" . $_FILES['file']['tmp_name'] . "' | cut -d: -f2 | cut -d, -f1");
What I'm trying to do:
file_get_contents() an online image, then save it to a directory on my server, with a new filename.
The save path / directory is writable. CHMOD permissions: 777
What I've tried:
file_put_contents($filepath, file_get_contents($image_url)); // SAVES 0KB IMAGE
copy($image_url,$filepath); // SAVES 0KB IMAGE
cURL // SAVES 0KB IMAGE
So I'm already getting confused why none of this is working, when it should be...
Here are the relevant values inside my PHPinfo:
allow_url_fopen = On
allow_url_include = On
open_basedir = no value
post_max_size = 8M
upload_max_filesize = 50M
upload_tmp_dir = no value
max_execution_time = 18000
max_file_uploads = 20
max_input_nesting_level = 64
max_input_time = 60
max_input_vars = 1000
memory_limit = 256M
And here is my full PHP code (I'm now using a function to save the image, because I'm just about desperate enough to try anything):
function save_image($inPath,$outPath)
{ // Download images from remote server
$in= fopen($inPath, "rb");
$out= fopen($outPath, "wb");
while ($chunk = fread($in,8388608))
{
fwrite($out, $chunk, 8388608);
}
fclose($in);
fclose($out);
}
// THE ORIGINAL IMAGE TO GET
$image_url = 'http://m1.i.pbase.com/u38/antidote3/upload/31848351.Cute.jpg';
// THE IMAGE EXTENSION
$image_type = substr(strrchr($image_url,"."),1);
// THE NEW FILE NAME
$filename = 'product5_'. md5($image_url . $sku).'.'.$image_type;
// THE SAVE PATH
// OUTPUT: /var/www/site/media/catalog/product/FILE_NAME.FILE_TYPE
$filepath = Mage::getBaseDir('media') . DS . 'catalog'. DS . 'product'. DS . $filename;
// SAVE THIS BIATCH!
save_image($image_url, $filepath);
// OTHER SAVE METHODS
// file_put_contents($filepath, file_get_contents($image_url));
// copy($image_url,$filepath);
Running strlen(file_get_contents($image_url)) on the image returns a big fat 0.
But shouldn't it work with the following enabled on my server?
allow_url_fopen = On
allow_url_include = On
Apparently, the problem doesn't lie on the writing, but file_get_contents($image_url) doesn't have anything inside it.
Any ideas why? Thanks!
Other Information:
Platform: Magento
Language: PHP
PHP Version: 5.4.6
Maybe you should try something like this (using feof and fread the right way!) - I also changed how you are grabbing the extension:
<?php
function save_image($inPath, $outPath) {
$in = fopen($inPath, "rb");
$out = fopen($outPath, "wb");
while (!feof($in)) {
$read = fread($in, 8192);
fwrite($out, $read);
}
fclose($in);
fclose($out);
}
// THE ORIGINAL IMAGE TO GET
$image_url = 'http://m1.i.pbase.com/u38/antidote3/upload/31848351.Cute.jpg';
// THE IMAGE EXTENSION
$image_type = end(explode(".", $image_url));
// THE NEW FILE NAME
$filename = 'product5_'. md5($image_url . $sku).'.'.$image_type;
// THE SAVE PATH
// OUTPUT: /var/www/site/media/catalog/product/FILE_NAME.FILE_TYPE
$filepath = Mage::getBaseDir('media') . DS . 'catalog'. DS . 'product'. DS . $filename;
// SAVE THIS BIATCH!
save_image($image_url, $filepath);
?>
I not sure will it help. Can you try this way?
function save_image($inPath,$outPath) {
$inbuf = file_get_contents($inPath);
$fp = fopen($outPath,'w');
fwrite($fp,$inbuf);
fclose($fp);
}
note: it was a typo, $buf intead of $inbuf.
The answer is: a firewall rule on the server was causing it. Thanks everyone for the help!
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);
Hello I am usign the below code to zip a package on upload:
$nameFile = $_FILES['file']['name'];
$tmpName = $_FILES['file']['tmp_name'];
$download_folder = './CopyrightFiles/';
$zip = new ZipArchive();
$fileconpress = $download_folder.$nameFile.".zip";
$conpress = $zip->open($fileconpress, ZIPARCHIVE::CREATE);
if ($conpress === true)
{
$zip->addFile($tmpName);
$zip->close();
echo $fileconpress."<br/>";
echo "yess !! Success!!!! ";
}
else echo " Oh No! Error";
It seems to work ok.
But there are two issues.
First issue it saves the file also with the original extension, something like : image.JPG.zip
Also when I then move the zip package to my local computer (Mac) and I open the ZIP inside I can find only a tmp folder with a binary file inside and NOT the image or the file that should be there!
What the hell is going on?
Please advise
Thank you
That's because your "binary" file is just the temporary name that PHP used to temporarily stored the uploaded file as. That's why it's "tmp_name" in the $_FILES array.
Try this:
$zip->addFile($tmpName, $nameFile);
The second parameter lets you specify what the file's name should be within the zip.
To prevent 'file.jpg.zip', try:
$fileconpress = $download_folder . pathinfo($_FILES['file']['name'], PATHINFO_FILENAME) . ".zip";
Issue #1:
You need to manually remove the extension:
$filename = explode('.', $_FILES['file']['name']);
$filename = $filename[0];
Issue #2:
$tmpName does not contain the filename of the file. You need to pass the $localname parameter in addFile(). See http://php.net/manual/en/function.ziparchive-addfile.php.