Unable to copy image from URL in PHP with upload class - php

I'm trying to make a upload class with PHP. so this is my first PHP class:
//Create Class
class Upload{
//Remote Image Upload
function Remote($Image){
$Content = file_get_contents($Image);
if(copy($Content, '/test/sdfsdfd.jpg')){
return "UPLOADED";
}else{
return "ERROR";
}
}
}
and usage:
$Upload = new Upload();
echo $Upload->Remote('https://www.gstatic.com/webp/gallery/4.sm.jpg');
problem is, this class is not working. where is the problem? I'm new with PHP classes and trying to learn it.
thank you.

copy expects filesystem paths, e.g.
copy('/path/to/source', '/path/to/destination');
You're passing in the literal image you fetched, so it's going to be
copy('massive pile of binary garbage that will be treated as a filename', '/path/to/destination');
You want
file_put_contents('/test/sdfsdfg.jpg', $Content);
instead.

PHP's copy() function is used for copying files that you have permission to copy.
Since you're getting the contents of the file first, you could use fwrite().
<?php
//Remote Image Upload
function Remote($Image){
$Content = file_get_contents($Image);
// Create the file
if (!$fp = fopen('img.png', 'w')) {
echo "Failed to create image file.";
}
// Add the contents
if (fwrite($fp, $Content) === false) {
echo "Failed to write image file contents.";
}
fclose($fp);
}

Since you want to download a image, you could also use the imagejpeg-method of php to ensure you do not end up with any corrupted file format afterwards (http://de2.php.net/manual/en/function.imagejpeg.php):
download the target as "String"
create a image resource out of it.
save it as jpeg, using the proper method:
inside your method:
$content = file_get_contents($Image);
$img = imagecreatefromstring($content);
return imagejpeg($img, "Path/to/targetFile");
In order to have file_get_contents working correctly you need to ensure that allow_url_fopen is set to 1 in your php ini: http://php.net/manual/en/filesystem.configuration.php
Most managed hosters disable this by default. Either contact the support therefore or if they will not enable allow_url_fopen, you need to use another attempt, for example using cURL for file download. http://php.net/manual/en/book.curl.php
U can use the following snippet to check whether its enabled or not:
if ( ini_get('allow_url_fopen') ) {
echo "Enabled";
} else{
echo "Disabled";
}

What you describe is more download (to the server) then upload. stream_copy_to_stream.
class Remote
{
public static function download($in, $out)
{
$src = fopen($in, "r");
if (!$src) {
return 0;
}
$dest = fopen($out, "w");
if (!$dest) {
return 0;
}
$bytes = stream_copy_to_stream($src, $dest);
fclose($src); fclose($dest);
return $bytes;
}
}
$remote = 'https://www.gstatic.com/webp/gallery/4.sm.jpg';
$local = __DIR__ . '/test/sdfsdfd.jpg';
echo (Remote::download($remote, $local) > 0 ? "OK" : "ERROR");

Related

PHP file_exists With Contents Instead of Name?

Is there a function built into PHP that acts like file_exists, but given file contents instead of the file name?
I need this because I have a site where people can upload an image. The image is stored in a file with a name determined by my program (image_0.png image_1.png image_2.png image_3.png image_4.png ...). I do not want my site to have multiple images with the same contents. This could happen if multiple people found a picture on the internet and all of them uploaded it to my site. I would like to check if there is already a file with the contents of the uploaded file to save on storage.
This is how you can compare exactly two files with PHP:
function compareFiles($file_a, $file_b)
{
if (filesize($file_a) == filesize($file_b))
{
$fp_a = fopen($file_a, 'rb');
$fp_b = fopen($file_b, 'rb');
while (($b = fread($fp_a, 4096)) !== false)
{
$b_b = fread($fp_b, 4096);
if ($b !== $b_b)
{
fclose($fp_a);
fclose($fp_b);
return false;
}
}
fclose($fp_a);
fclose($fp_b);
return true;
}
return false;
}
If you keep the sha1 sum of each file you accept you can simply:
if ($known_sha1 == sha1_file($new_file))
You can use a while loop to look look through the contents of all of your files. This is shown in the example below :
function content_exists($file){
$image = file_get_contents($file);
$counter = 0;
while(file_exists('image_' . $counter . '.png')){
$check = file_get_contents('image_' . $counter . '.png');
if($image === $check){
return true;
}
else{
$counter ++;
}
}
return false;
}
The above function looks through all of your files and checks to see if the given image matches an image that is already stored. If the image already exists, true is returned and if the image does not exist false is returned. An example of how you can use this function shown is below :
if(content_exists($_FILES['file']['tmp_name'])){
// upload
}
else{
// do not upload
}
You could store hashed files in a .txt file separated by a \n so that you could use the function below :
function content_exists($file){
$file = hash('sha256', file_get_contents($file));
$files = explode("\n", rtrim(file_get_contents('files.txt')));
if(in_array($file, $files)){
return true;
}
else{
return false;
}
}
You could then use it to determine whether or not you should save the file as shown below :
if(content_exists($_FILES['file']['tmp_name'])){
// upload
}
else{
// do not upload
}
Just make sure that when a file IS stored, you use the following line of code :
file_put_contents('files.txt', hash('sha256', file_get_contents($file)) . "\n");

PHP SSH move file to another directory [duplicate]

I am uploading files to a server using php and while the move_uploaded_file function returns no errors, the file is not in the destination folder. As you can see I am using the exact path from root, and the files being uploaded are lower than the max size.
$target = "/data/array1/users/ultimate/public_html/Uploads/2010/";
//Write the info to the bioHold xml file.
$xml = new DOMDocument();
$xml->load('bioHold.xml');
$xml->formatOutput = true;
$root = $xml->firstChild;
$player = $xml->createElement("player");
$image = $xml->createElement("image");
$image->setAttribute("loc", $target.basename($_FILES['image']['name']));
$player->appendChild($image);
$name = $xml->createElement("name", $_POST['name']);
$player->appendChild($name);
$number = $xml->createElement("number", $_POST['number']);
$player->appendChild($number);
$ghettoYear = $xml->createElement("ghettoYear", $_POST['ghetto']);
$player->appendChild($ghettoYear);
$schoolYear = $xml->createElement("schoolYear", $_POST['school']);
$player->appendChild($schoolYear);
$bio = $xml->createElement("bio", $_POST['bio']);
$player->appendChild($bio);
$root->appendChild($player);
$xml->save("bioHold.xml");
//Save the image to the server.
$target = $target.basename($_FILES['image']['name']);
if(is_uploaded_file($_FILES['image']['tmp_name']))
echo 'It is a file <br />';
if(!(move_uploaded_file($_FILES['image']['tmp_name'], $target))) {
echo $_FILES['image']['error']."<br />";
}
else {
echo $_FILES['image']['error']."<br />";
echo $target;
}
Any help is appreciated.
Eric R.
Most like this is a permissions issue. I'm going to assume you don't have any kind of direct shell access to check this stuff directly, so here's how to do it from within the script:
Check if the $target directory exists:
$target = '/data/etc....';
if (!is_dir($target)) {
die("Directory $target is not a directory");
}
Check if it's writeable:
if (!is_writable($target)) {
die("Directory $target is not writeable");
}
Check if the full target filename exists/is writable - maybe it exists but can't be overwritten:
$target = $target . basename($_FILES['image']['name']);
if (!is_writeable($target)) {
die("File $target isn't writeable");
}
Beyond that:
if(!(move_uploaded_file($_FILES['image']['tmp_name'], $target))) {
echo $_FILES['image']['error']."<br />";
}
Echoing out the error parameter here is of no use, it refers purely to the upload process. If the file was uploaded correctly, but could not be moved, this will still only echo out a 0 (e.g. the UPLOAD_ERR_OK constant). The proper way of checking for errors goes something like this:
if ($_FILES['images']['error'] === UPLOAD_ERR_OK) {
// file was properly uploaded
if (!is_uploaded_File(...)) {
die("Something done goofed - not uploaded file");
}
if (!move_uploaded_file(...)) {
echo "Couldn't move file, possible diagnostic information:"
print_r(error_get_last());
die();
}
} else {
die("Upload failed with error {$_FILES['images']['error']}");
}
You need to make sure that whoever is hosting your pages has the settings configured to allow you to upload and move files. Most will disable these functions as it's a sercurity risk.
Just email them and ask whether they are enabled.
Hope this helps.
your calls to is_uploaded_file and move_uploaded_file vary. for is_uploaded_file you are checking the 'name' and for move_uploaded_file you are passing in 'tmp_name'. try changing your call to move_uploaded_file to use 'name'

Can PHP decompress a taz file? (.tar.Z)

I have tried to use Zlib to decompress the file, but it just said "Data error" and gave me an empty file.
This is the code I tried:
// Open a new temp file to write new file to
$tempFile = fopen("tempFile", "w");
// Make sure tempFile is empty
ftruncate($tempFile, 0);
// Write new decompressed file
fwrite($tempFile, zlib_decode(file_get_contents($path))); // $path = absolute path to data.tar.Z
// close temp file
fclose($tempFile);
I have also tried to decompress it in parts, going from .tar.Z to .tar to just a file. I tried using lzw functions to take off the .Z, but I was unable to make it work. Is there a way to do this?
EDIT:
Here is some more code I have tried. Just to make sure the file_get_contents was working. I still get a "data error".
$tempFile = fopen("tempFile.tar", "w");
// Make sure tempFile is empty
ftruncate($tempFile, 0);
// Write new decompressed file
$contents = file_get_contents($path);
if ($contents) {
fwrite($tempFile, gzuncompress($contents));
}
// close temp file
fclose($tempFile);
EDIT2: I think the reason why LZW was not working is because the contents of the .tar.Z file looks like this:
��3dЀ��0p���a�
H�H��ŋ3j��#�6l�
The LZW functions I have tried both use ASCII characters in their dictionaries. What kind of characters are these?
So you want to decompress a taz file natively with PHP? Give my new extension a try!
lzw_decompress_file('3240_05_1948-1998.tar.Z', '3240_05_1948-1998.tar');
$archive = new PharData('/tmp/3240_05_1948-1998.tar');
mkdir('unpacked');
$archive->extractTo('unpacked');
Also note, the reason the zlib functions aren't working is because you need LZW compression, not gzip compression.
according to this url https://kb.iu.edu/d/acsy you can try
<?php
$file = '/tmp/archive.z';
shell_exec("uncompress $file");
if you don't have Unix like OS check https://kb.iu.edu/d/abck for appropriate program.
The file is compressed with LZW compression, and I tried a few but there seems to be no reliable method for decompressing these in PHP. Cosmin's answer contains the correct first step but after using your system's uncompress utility to decompress the file, you still have to extract the TAR file. This can be done with PHP's built-in tools for handling its custom PHAR files.
// the file we're getting
$url = "ftp://ftp.ncdc.noaa.gov/pub/data/hourly_precip-3240/05/3240_05_2011-2011.tar.Z";
// where to save it
$output_dir = ".";
// get a temporary file name
$tempfile = sys_get_temp_dir() . basename($url);
// get the file
$compressed_data = file_get_contents($url);
if (empty($compressed_data)) {
echo "error getting $url";
exit;
}
// save it to a local file
$result = file_put_contents($tempfile, $compressed_data);
if (!$result) {
echo "error saving data to $tempfile";
exit;
}
// run the system uncompress utility
exec("/usr/bin/env uncompress $tempfile", $foo, $return);
if ($return == 0) {
// uncompress strips the .Z off the filename
$tempfile = preg_replace("/.Z$/", "", $tempfile);
// remove .tar from the filename for use as a directory
$tempdir = preg_replace("/.tar$/", "", basename($tempfile));
try {
// extract the tar file
$tarchive = new PharData($tempfile);
$tarchive->extractTo("$output_dir/$tempdir");
// loop through the files
$dir = new DirectoryIterator($tempdir);
foreach ($dir as $file) {
if (!$file->isDot()) {
echo $file->getFileName() . "\n";
}
}
} catch (Exception $e) {
echo "Caught exception untarring: " . $e->getMessage();
exit;
}
} else {
echo "uncompress returned error code $return";
exit;
}
Please try this.
<?php
try {
$phar = new PharData('myphar.tar');
$phar->extractTo('/full/path'); // extract all files
$phar->extractTo('/another/path', 'file.txt'); // extract only file.txt
$phar->extractTo('/this/path',
array('file1.txt', 'file2.txt')); // extract 2 files only
$phar->extractTo('/third/path', null, true); // extract all files, and overwrite
} catch (Exception $e) {
// handle errors
}
?>
Source : http://php.net/manual/en/phardata.extractto.php
I haven't tested it but i hope it will work for you.

PHP image wrong mimetype

I'm uploading images from my Android app to my server. The app uses the android camera intent and upload via PHP script is ok.
I want to verify if the uploaded files are real images, I'm not checking the extension but the mimetype (I suppose this is the best way to do it, tell me if I'm wrong).
I'm using a Slackware Linux Apache server and I'm trying this code:
....
$finfo = finfo_open(FILEINFO_MIME, '/etc/httpd/magic');
....
fwrite($fp, finfo_file($finfo, "file.jpg"));
....
But I'm getting "application/octet-stream; charset=binary" instead of "image/jpeg; charset=binary" which is given from "file -i file.jpg" (shell command).
What's the problem?
Solved using $finfo = finfo_open(FILEINFO_MIME); instead of the other line. I think the default magic file is not the same that I was specifing.
As refered on www.php.net/manual/en/ref.fileinfo.php:
<?php
function is_jpg($fullpathtoimage){
if(file_exists($fullpathtoimage)){
exec("/usr/bin/identify -format %m $fullpathtoimage",$out);
//using system() echos STDOUT automatically
if(!empty($out)){
//identify returns an empty result to php
//if the file is not an image
if($out == 'JPEG'){
return true;
}
}
}
return false;
}
?>
Alternately, if you've got execution rights and want to use a "hacky" solution, you can simply do what you've already done (using file -i path with shell_exec):
<?php
function shell_get_mime_type($path) {
if (is_readable($path)) {
$command = 'file -i "' . realpath($path) . '"';
$shellOutput = trim(shell_exec($command));
//eg. "nav_item.png: image/png; charset=binary"
if (!empty($shellOutput)) {
$colonPosition = strpos($shellOutput, ':');
if ($colonPosition !== false) {
return rtrim(substr($shellOutput, $colonPosition + 1));
}
return $shellOutput;
}
}
return false;
}
?>
Try to use function mime_content_type().

Unzipping to a variable

I need to process the contents of a zipped file, but I can't change the permissions on the server where my program will be hosted.
This means that I can't download the zip file to the server, so I need to read the contents of the file into a variable without writing it to the file system.
Can I grab the string contents of such variable and get the unzipped contents into a new variable?
So far, I've looked into using the zip php extension, and the pclzip library, but both need to use actual files.
This is what I want to do in pseudo code:
$contentsOfMyZipFile = ZipFileToString();
$myUnzippedContents = libUnzip($contentsOfMyZipFile);
Any ideas?
Look at this example.
<?php
$open = zip_open($file);
if (is_numeric($open)) {
echo "Zip Open Error #: $open";
} else {
while($zip = zip_read($open)) {
zip_entry_open($zip);
$text = zip_entry_read($zip , zip_entry_filesize($zip));
zip_entry_close($zip);
}
print_r($text);
?>
I use this in my project:
function unzip_file( $data ) {
//save in tmp zip data
$zipname = "/tmp/file_xxx.zip";
$handle = fopen($zipname, "w");
fwrite($handle, $data);
fclose($handle);
//then open and read it.
$open = zip_open($zipname);
if (is_numeric($open)) {
echo "Zip Open Error #: $open";
} else {
while ($zip = zip_read($open)) {
zip_entry_open($zip);
$text = zip_entry_read($zip, zip_entry_filesize($zip));
zip_entry_close($zip);
}
}
/*delete tmp file and return variable with data(in this case plaintext)*/
unlink($zipname);
return $text;
}
I hope it helps you.

Categories