I am having a problem in getting a image uploading to the server (first I convert it to .png and resize it):
In functions.php
function imageUploadedResize($source, $target,$nWidth, $nHeight)
{
$sourceImg = Imagecreatefromstring(file_get_contents($source));
if ($sourceImg === false)
{
return false;
}
$width = imagesx($sourceImg);
$height = imagesy($sourceImg);
$targetImg = imagecreatetruecolor($nWidth, $nHeight);
imagecopyresized($targetImg, $sourceImg, 0, 0, 0, 0, $nWidth,$nHeight,$width, $height);
imagedestroy($sourceImg);
imagepng($targetImg, $target);
imagedestroy($targetImg);
}
In uploadtoServer.php
if(isset($_POST["fileToUpload"]))
{
$target_dir = "img/data/";
$fn = $_FILES['fileToUpload']['tmp_name'];
$newFileName = mysqli_insert_id($link).".png";
header('Content-type: image/png');
imageUploadedResize($fn, $target_dir.$newFileName, 45,60);
}
If I change $fn to a static image like "https://pbs.twimg.com/profile_images/54789364/JPG-logo-highres.jpg" it works so I guess I am having a problem in $fn. Any thoughts what can it be?
Part 1:
Form input
As Johnathan mentioned, you're checking isset($_POST["fileToUpload"]) when a file upload form will supply the value in the $_FILES array. So you need to change your reference from $_POST to $_FILES otherwise it will always return false.
Edit: As your comment states you are getting 100% false, you should use a more specific qualifier such as if($_FILES['fileToUpload']['error'] == 0) .
Your HTML form submitting the data needs to be enctype="multipart/form-data" otherwise your server will not collect anything file shaped from your form. HTML forms also need to be set in the POST method.
Part 2
File storage:
Your references to file system storage for the image, such as $target_dir = "img/data/"; are relative, so that means that the value of $target_dir needs to be the child of the file that is calling that script block.
It would probably help you a lot to use Absolute file system references, typically (but not exclusively) using $_SERVER['DOCUMENT_ROOT']."/img/data";
This example will store data in the www.your-web-site.com/img/data location.
Part 3
Displaying the image.
You have a header setting content type to image/png but you do not actually output the image, instead saving it to the file reference mentioned above. If you want to output the image to the browser, you need to skip saving it so:
imagepng($targetImg, NULL);
This will then output the image in $targetImg straight out to the browser. At the moment you appear to be saving it but not displaying it, despite setting the image header which means that any output to browser is expected to be an image content.
Some systems have a restriction on freshly uploaded data and prevent that data being handled too freely, to get around this it is advisable to use move_upladed_file to save the file to a "proper" destination and then access it to output to the browser.
Further Notes:
You should be checking $_FILES['fileToUpload']['error'] before acting on the file, as this will tell you if a file is present. using isset is a bad (very ambiguous) idea on this as the array can still be set, even if the file has not been uploaded.
You should use PHP error logging. You should not use error supression #.
Related
There are a bunch of questions of with the same title as this one.
For instance
How to output images using php?
Output as an image using PHP
How to output image and download using php
Invariably the answer is some variation of
add header('Content-type: image/jpeg'); to your code
Which is an important part of the answer, no doubt, but leaves out some vital steps I really cannot work out.
Now, there is obvious benefit to fetching an image using php when the image is situated below the root directory.
So suppose you have a web page
<?php
require_once("load_a_scripts.php");
print("lots of html");
// fetch image from below root directory and output in HTML
?>
<img id="this_one" src="" height="200" width="200" />
And you want to output the image this_one, above?
PHP can be used to fetch the required file using readfile(), but that will not be terribly useful here (at best you will get random unicode output instead of a proper image here).
The solution to prevent garbled output is to use
header('Content-type: image/jpeg');
This clearly seems inappropriate here. Not only is there output, which would make setting the header impossible, but even if this course of action is successful, the best that one can hope for is a download prompt for the image. Again, this is not desired functionality.
So some solutions suggest some external code, like "image.php" that will have its own header and will fetch the image, and so on. However, there's again some issues with this.
How will image.php know what what image it is you want?
<?php header('Content-Type:'.$photo);
if(isset($photo)&&isset($type)){
if(strlen($photo)>15||strlen($type)>6){
die();
}
$photo = strtolower($photo);
$photo = preg_replace('/[^a-z0-9 -]+/', '', $photo);
$photo = str_replace(' ', '-', $photo);
$photo = trim($photo, '-');
$type = strtolower($type);
$type = preg_replace('/[^a-z0-9 -]+/', '', $type);
$type = str_replace(' ', '-', $type);
$type = trim($type, '-');
readfile('../img/'.$user_id.$photo);
}
The parameters relating to the image name ($photo) and mime ($type) can hypothetically be sent using GET, but again, what sends these parameters, and how?
Some answers seemed to indicate that you could directly link to the external image.php as if it were an image
<img src="image.php" />
But this again raises the question about how image.php knows what the values for $photo and $type.
You have two basic options: first, using an external image-loader/handler script (e.g. <img src="image.php?i=sunshine.jpg" />); second, base64-encoding the image data (e.g. <img src="data:image/png;base64, i26dfdXAd..." />). The second option will make your HTML bloat like there's no tomorrow. So let's simply look at the image.php handler approach.
How does the handler know what image to show? It'll need a query string, e.g. image.php?i=sunshine.jpg; or image.php?i=sunshine&x=jpg; or image.php?i=sunshine&x=jpg&s=600, if you wanted to load a particular size, and so on. You will have to use that format in your HTML source, there's no script that would automagically know what image to load. Then, it's "who" (you), not "what", that sends the parameters. You'll want to make sure that the variables are properly sanitized (as your sample handler is doing); like any user-modifiable input, they shouldn't be trusted, especially anywhere near filesystem operations (directory traversal, etc.). These variables will be available as $_GET['i'], $_GET['x'], etc. to your handler script.
If you feel like URL parameters are a hassle, or just look dirty, you could always rewrite URLs. Link an image as <img src="images/sunshine.jpg" />, and have a .htaccess rewrite rule in place in the /images/ folder (containing only your script) that passes all image requests to your handler script. See the "htaccess redirect all images to handler" Q/A for an example. You could also use this approach for handling down-scaled image versions, with source URLs like <img src="images/sunshine__600.jpg" /> mapped to a rewrite rule.
On the use of readfile() (the most memory-friendly way of blurting out large chunks of data), as long as you output the header('Content-type: image/jpeg'); (or other appropriate MIME header) before your readfile() call, it will work in the desired way. That is to say, browser won't know the difference between images served directly from the filesys by the webserver, or images served from outside the webroot with a handler. It's just data with an image HTTP header.
Edit: Bonus. Coded a minimalist safe-to-deploy file-handler.
<?php
/*
* Receive image call as: <img src="img.php?i=name.jpg" />
* Output matching image file from $basepath directory
*/
$basepath = '../images/'; // Path to image folder
$mimes = [ // Allowed image types:
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'svg' => 'image/svg+xml',
];
!isset($_GET['i']) && die(); // Nothing to do here.
// Parse & Verify Extension
$ext = strtolower(pathinfo($_GET['i'], PATHINFO_EXTENSION));
!isset($mimes[$ext]) && die('Invalid filetype!'); // If MIME N/A: die!
// Parse & Sanitize Filename
$file = basename($_GET['i']);
$file = preg_replace('#[^[:alnum:] ._-]#', '', $file);
$filepath = realpath($basepath . $file);
$filepath === false && die('Invalid filename!'); // If image N/A: die!
// Output MIME header and image:
header('Content-Type:' . $mimes[$ext]);
readfile($filepath);
exit;
If you need to accommodate jpeg etc. variants, simply a) duplicate the MIME definitions in the $mimes array, or b) add an extension normalization routine. If you need to access images in subfolders, e.g. ?i=sun/shine.jpg, rework the filename parse/sanitize routine without basename. (Be sure you're safe from directory traversal!). Characters other than [:alnum:] ._-] are removed from the requested filename. Modify the regex as necessary.
I have a question about the application generate QR code image.
I have an application when clients click a button there will generate a QR code image, my way is store in the project library, then print <img> with the url to the screen. then clients can see it.
But I have a doubt, if there are multi clients using the QR code at the same time, whether there will get a mix?
my code is bellow:
function generate_qrcode($url){
$filename = 'hante_qrcode.png';
$errorCorrectionLevel = 'L';
$matrixPointSize = 4;
//generate QR code image
$o = QRcode::png($url, $filename, $errorCorrectionLevel, $matrixPointSize, 2);
echo "<pre>";
print_r($o);
print_r('<img src="hante_qrcode.png">');
}
if there get mix, how to solve this problem?
But I have a doubt, if there are multi clients using the QR code at the same time, whether there will get a mix?
yes
how to solve this problem?
there are two ways to solve this problem
you can provide unique name for every files like using timestamp using time() function or with user ID. cause as per you are passing parameters while generating qr code you need to store the file. without saving file also possible but in that case you can't configure pixel size and frame size. you can refer this for PHP QR code-Examples
don't store image on server and find some js to generate qr code directly from client side.
having a one demo for that check if you can use it
var qrcode = new QRCode("qrcode");
qrcode.makeCode('https://stackoverflow.com');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
<div id="qrcode"></div>
Of course it will be overwritten.
Solution 1
Create unique filename for every image. This way you can save your images for use later. Another benefit of this, you don't have to create image again for same url.
$filename = md5($url) . ".png";
if(!file_exists($filename)){
$o = QRcode::png($url, $filename, ...);
}
echo '<img src="'.$filename.'">';
Solution 2
If you don't want to save images for disk space reasons you can serve image directly. In your code, user sends request to index.php and fetch image address as response. After then browser makes another request to get image. You can return image rather than returning html.
// image.php
// Still we want to give uniqe filename because we can get another request while one request is processing
$filename = md5(microtime) . "_qr.png";
$o = QRcode::png($url, $filename, ...);
$image = file_get_contents($filename);
// remove the file after stored in a variable
unlink($filename);
header('Content-Type: image/jpeg');
header('Content-Length: ' . filesize($image));
echo $image;
// index.html
<img src="image.php?url=someurl">
I have the following scenario. I have about around 600 pictures. Most of theme have in bottom a logo which should be cut it out because branding issue, but not all of theme.(with ftp and photoshop would be a challange)The approach what I was thinking about I list all of my images form folders and I add to theme a hyperlink which should fire on a method class which cuts out 57px from bottom, because the image listing limited to height and width, after cutting should not be present on the page
the url looks like
cut.php?target=http://example.com/hideit/2012/03/myimage.jpg
I want to reset the get parameter after execution to avoid problems on page refresh while would cut again from that image the defined pixels. I was trying the following
function cutAndsave($jpg){
$folder = explode('/', $jpg);
$path = 'I:\\xampp\\htdocs\\hideit\\'. $folder[4]. '\\'. $folder[5] .'\\'.$folder[6] ;
list($width, $height) = getimagesize($jpg);
$offset_x = 0;
$offset_y = 0;
$new_height = $height - 57;
$new_width = $width;
$image = imagecreatefromjpeg($jpg);
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopy($new_image, $image, 0, 0, $offset_x, $offset_y, $width, $height);
header('Content-Type: image/jpeg');
imagejpeg($new_image,$path, 90);
header("Location: /cat.php/");
die();
}
but the last header call won't work in my case
Your concrete problem at hand is that you're trying to send an HTTP header after you output an image. HTTP headers can only be sent before any content; they're headers after all.
The bigger problem is that the idea is nonsense.
The client requests a URL, example.com/image.php?id=42.jpg. You may think of this URL as a filename. The image is identified by the filename/URL. Different URL, different image. It also doesn't matter that this is a PHP script and not a physical file on a hard disk somewhere, that detail is irrelevant to the client. The client requests the URL and receives an image in return, that's all that matters. Whether the image is just read as is from a data storage, is resized by a script on the fly, is live drawn by unicorns behind the scenes, that all doesn't matter; it's an implementation detail.
URL request, response. That's the important concept you need to grok for working with web servers.
As such, "resetting URL parameters" is pointless. You can't do that. You can redirect the client to a different URL, but that's a different file/URL then. If you want the client to get the image, you respond with an image whenever the client asks for the URL. If the user refreshes the page so the client requests the URL again, so be it.
If you do not want to do the image cutting again and again, cache the resized file. In code, check:
Oh, somebody's requesting image #42.
Do I have a resized version of image #42 already?
If no, create a resized version and save it somewhere.
Serve the resized image #42.
On top of that you can set HTTP headers that influence the client's caching behavior, so the client will keep the image in its cache and not request it again every time.
In case it's also as simple as not overwriting the original. Always keep the original intact, the cut version should be a copy of it. You can either generate that copy as described above, or when the original is uploaded. But don't change the behavior of a URL depending on whether you have already processed the image or not.
You have an error in line header("Location: /cat.php/");
It should be
header("Location: /cut.php");
if you just want to go back to last page.
If you want to additionally show your image you can do
header("Location: /cut.php?show=$path")
and then do a script in your file which prints an <img> tag.
The following problem I can't really wrap my mind around, so really if you guys can't be bothered to supply the entire code some tips leading in the right direction would be great!
So, I have a script where users can upload images to a server. PHP takes care of validating the file and saving it using a new filename in another folder, neither known by the client. Now, the client should be able to see the uploaded image, in html simply:
style="background-image:url('testimagegif.gif');
But preferably the client should not be able to see the path nor the file name of the image saved on the server. I know about using header('Content-type: ... for forcing the client browser to download files, but I do not see how this, nor any similar solution could be applied to this case. Same goes for readfile. If I use it the browser simply downloads the image, not placing it in the html.
You should probably be moving the files into a publicly readable folder on your webserver if you want to serve them.
Otherwise, you'll need something like readfile()
There are two options for this, you could use the data protocol, which would embed the whole image into the URL of the background ( this isn't recommended if the image is bigger than a few kb. ) or you can use a script to present the image by encoding or recording a unique key for the image, eg bg.php?id=4323-34442-3432-4532 which checks a db for the id to retrieve the file path then echoes the content with the right content type.
Some examples;
based on the Data URI wikipedia page
Data URI Method
Assuming a function like this;
function data_uri($fileID) {
$fRecord = mysql_fetch_array(
mysql_select("SELECT filePath, mimeType from fileTable WHERE fileID = " $fileID . ";")
);
$contents = file_get_contents($fRecord['filePath']);
$base64 = base64_encode($contents);
return "data:$fRecord['mimeType'];base64,$base64";
}
Then in your html/php page you'd have the following snippet
style="background-image:url('<?php echo data_uri($fileID);?>'
PHP Image Dump
Assuming a function like this;
// Given a filename and a mimetype; dump the contents to the screen
function showDocumentContent($fileID){
$fRecord = mysql_fetch_array(
mysql_select("SELECT filePath, mimeType from fileTable WHERE fileID = " $fileID . ";")
);
header( 'Content-Encoding: none', true );
header( 'Content-Type: ' . $fRecord['mimeType'], true );
echo readfile( $fRecord['filePath'] );
}
Then in your html page you'd have this;
style="background-image:url('image.php?fileID=123')
In the first case, images larger than a few KB will result in equally large HTML pages, and may not be supported in browsers consistently. In the second case, you'd effectively have created a php script that is pretending to be an image. In both cases, the real path to the binary files on your server is abstracted away by storing a mapping in a database.
If you store the paths to the files somewhere like a database or a file, you can use readfile() to output the file once you retrieve the path.
Combine that with the content-type header, and set the background-image URL to the PHP script with the correct query string like so:
style="background-image:url('script.php?img=30382');"
You must expose some path to the client, because their browser has to access the file. You can use your webserver config to serve at an indirected location, or serve the image with PHP and have the real path in a call to readfile()
I am trying to take a pic upload from a mobile device to a server. We are building with PhoneGap (Javascript), so we are having turn it into a string in order to send it to the server. I am having problems once I receive it, to turn it back into a readable image file.
Simply put, I need to take a string and a file name sent to me, decode it, convert it into a .png, then crop it into a circular image.
This is what I have going on currently
if (isset($_POST['file']))
{
//Result variable
$result = false;
$pic = base64_decode($_POST['file']);
$filename = $_POST['filename'];
if (strlen($pic) > 9 )
{
$fh = fopen("/var/www/pics/events/".$filename, 'w') or die("can't open file");
fwrite($fh, $pic);
fclose($fh);
}
}
I think I can get the rest of the code to work if I can figure out what I am doing wrong here that makes it not save properly as a image file? The file uploads correctly, but it stores with out an extension, and when I point to it in my browser, it comes up like it is supposed to be an image file, but never displays the image. That little broken picture icon with the colored shapes is what I get when I direct to it's location.
Do I need to be aware of what image type is being sent during this process at all? How is it knowing if it is a .gif, .jpg/jpeg, .png, etc...?
Thanks in advance for any help!
Nathan
For Security reasons you should sanitize the file name to prevent directory traversal.
On a brighter note, make sure the file is saved with the proper extension; if you are already saving with the correct extension you could have an encoding issue from the app.
If neither of the previous possibilities are the case make sure that your String Size does not exceed the maximum POST size limit in your php.ini; if that is the case increase the size limit.