Giải pháp thiết kế web động với PHP - p 24 pps

10 350 0
Giải pháp thiết kế web động với PHP - p 24 pps

Đang tải... (xem toàn văn)

Thông tin tài liệu

USING PHP TO MANAGE FILES 211 2. Remove any default code created by your script editor, and insert the following code: <?php // define error page $error = 'http://localhost/phpsols/error.php'; // define the path to the download folder $filepath = 'C:/xampp/htdocs/phpsols/images/'; $getfile = NULL; // block any attempt to explore the filesystem if (isset($_GET['file']) && basename($_GET['file']) == $_GET['file']) { $getfile = $_GET['file']; } else { header("Location: $error"); exit; } if ($getfile) { $path = $filepath . $getfile; // check that it exists and is readable if (file_exists($path) && is_readable($path)) { // get the file's size and send the appropriate headers $size = filesize($path); header('Content-Type: application/octet-stream'); header('Content-Length: '. $size); header('Content-Disposition: attachment; filename=' . $getfile); header('Content-Transfer-Encoding: binary'); // open the file in read-only mode // suppress error messages if the file can't be opened $file = @fopen($path, 'r'); if ($file) { // stream the file and exit the script when complete fpassthru($file); exit; } else { header("Location: $error"); } } else { header("Location: $error"); } The only two lines that you need to change in this script are highlighted in bold type. The first defines $error, a variable that contains the URL of your error page. The second line that needs to be changed defines the path to the folder where the download file is stored. The script works by taking the name of the file to be downloaded from a query string appended to the URL and saving it as $getfile. Because query strings can be easily tampered with, CHAPTER 7 212 $getfile is initially set to NULL. This is an important security measure. If you fail to do this, you could give a malicious user access to any file on your server. The opening conditional statement uses basename() to make sure that an attacker cannot request a file, such as one that stores passwords, from another part of your file structure. As explained in Chapter 4, basename() extracts the filename component of a path, so if basename($_GET['file']) is different from $_GET['file'], you know theres an attempt to probe your server, and you can stop the script from going any further by using the header() function to redirect the user to the error page. After checking that the requested file exists and is readable, the script gets the files size, sends the appropriate HTTP headers, and opens the file in read-only mode using fopen(). Finally, fpassthru() dumps the file to the output buffer. But if the file cant be opened or doesnt exist, the user is redirected to the error page. 3. Test the script by creating another page and add a couple of links to download.php. Add a query string at the end of each link with file= followed by the name a file to be downloaded. Youll find a page called getdownloads.php in the ch07 folder, which contains the following two links: <p><a href="download.php?file=maiko.jpg">Download image 1</a></p> <p><a href="download.php?file=basin.jpg">Download image 2</a></p> 4. Click one of the links, and the browser should present you with a dialog box prompting you to download the file or choose a program to open it, as shown in Figure 7-6. Figure 7-6. The browser prompts the user to download the image, rather than opening it directly. Download from Wow! eBook <www.wowebook.com> USING PHP TO MANAGE FILES 213 5. Select Save File, and click OK, and the file should be saved rather than displayed. Click Cancel to abandon the download. Whichever button you click, the original page remains in the browser window. The only time download.php should load into the browser is if the file cannot be opened. Thats why its important to send the user to an error page if theres a problem. Ive demonstrated download.php with image files, but it can be used for any type of file because the headers send the file as a binary stream. This script relies on header() to send the appropriate HTTP headers to the browser. It is vital to ensure that there are no new lines or whitespace ahead of the opening PHP tag. If you have removed all whitespace and still get an error message saying “headers already sent,” your editor may have inserted invisible control characters at the beginning of the file. Some editing programs insert the byte order mark (BOM), which is known to cause problems with the ability to use the header() function. Check your program preferences to make sure the option to insert the BOM is deselected. Chapter review The file system functions arent particularly difficult to use, but there are many subtleties that can turn a seemingly simple task into a complicated one. Its important to check that you have the right permissions. Even when handling files in your own website, PHP needs permission to access any folder where you want to read files or write to them. The SPL DirectoryIterator and RecursiveDirectoryIterator classes make it easy to examine the contents of folders. Used in combination with the SplFileInfo methods and the RegexIterator, you can quickly find files of a specific type within a folder or folder hierarchy. When dealing with remote data sources, you need to check that allow_url_fopen hasnt been disabled. One of the most common uses of remote data sources is extracting information from RSS news feeds or XML documents, a task that takes only a few lines of code thanks to SimpleXML. In the next two chapters, well put some of the PHP solutions from this chapter to further practical use when working with images and building a simple user authentication system. CHAPTER 7 214 215 Chapter 8 Generating Thumbnail Images PHP has an extensive range of functions designed to work with images. Youve already met one of them, getimagesize(), in Chapter 4. As well as providing useful information about an images dimensions, PHP can manipulate images by resizing or rotating them. It can also add text dynamically without affecting the original; it can even create images on the fly. To give you just a taste of PHP image manipulation, Im going to show you how to generate a smaller copy of an uploaded image. Most of the time, youll want to use a dedicated graphics program, such as Photoshop or Fireworks, to generate thumbnail images because it gives you much better quality control. However, automatic thumbnail generation with PHP can be very useful if you want to allow registered users to upload images, but make sure they conform to a maximum size. You can save just the resized copy, or the copy along with the original. In Chapter 6, you built a PHP class to handle file uploads. In this chapter, youll create two classes: one to generate thumbnail images, the other to upload and resize images in a single operation. Rather than build the second class from scratch, youll base it on the Ps2_Upload class from Chapter 6. A great advantage of using classes is that theyre extensible—a class based on another can inherit the functionality of its parent class. Building the classes to upload images and generate thumbnails from them involves a lot of code. But once you have defined the classes, using them involves only a few lines of script. If youre in a rush or writing a lot of code makes you break out in a cold sweat, you can just use the finished classes. Come back later to learn how the code works. It uses many basic PHP functions that youll find useful in other situations. In this chapter youll learn about the following: • Scaling an image • Saving a rescaled image • Automatically resizing and renaming uploaded images • Creating a subclass by extending an existing one CHAPTER 8 216 Checking your servers capabilities Working with images in PHP relies on the GD extension. Originally GD stood for GIF Draw, but problems with the GIF patent led to support for GIF files being dropped in 1999, but the name GD stuck. The problematic patent expired in 2004, and GIF is once again supported. The all-in-one PHP packages recommended in Chapter 2 support GD by default, but you need to make sure the GD extension has also been enabled on your remote web server. As in previous chapters, run phpinfo() on your website to check the servers configuration. Scroll down until you reach the section shown in the following screenshot (it should be about halfway down the page). If you cant find this section, the GD extension isnt enabled, so you wont be able to use any of the scripts in this chapter on your website. Ask for it to be enabled or move to a different host. Strictly for abbreviation/acronym freaks: GIF stands for Graphics Interchange Format, JPEG is the standard created by the Joint Photographic Experts Group, and PNG is short for Portable Network Graphics. Although JPEG is the correct name for the standard, the “E” is frequently dropped, particularly when used as a filename extension. Manipulating images dynamically The GD extension allows you to generate images entirely from scratch or work with existing images. Either way, the underlying process always follows four basic steps: 1. Create a resource for the image in the servers memory while its being processed. GENERATING THUMBNAIL IMAGES 217 2. Process the image. 3. Display and/or save the image. 4. Remove the image resource from the servers memory. This process means that you are always working on an image in memory only and not on the original. Unless you save the image to disk before the script terminates, any changes are discarded. Working with images requires a lot of memory, so its vital to destroy the image resource as soon as its no longer needed. If a script runs very slowly or crashes, it probably indicates that the original image is too large. Making a smaller copy of an image The aim of this chapter is to show you how to resize images automatically on upload. This involves extending the Ps2_Upload class from Chapter 6. However, to make it easier to understand how to work with PHPs image manipulation functions, I propose to start by using images already on the server, and create a separate class to generate the thumbnail images. Getting ready The starting point is the following simple form, which uses PHP Solution 7-3 to create a drop-down menu of the photos in the images folder. You can find the code in create_thumb_win01.php and create_thumb_mac01.php in the ch08 folder. Copy it to a new folder called gd in the phpsols site root, and rename it create_thumb.php. <form id="form1" name="form1" method="post" action=""> <p> <select name="pix" id="pix"> <option value="">Select an image</option> <?php $files = new DirectoryIterator(' /images'); $images = new RegexIterator($files, '/\.(?:jpg|png|gif)$/i'); foreach ($images as $image) { ?> <option value="C:/xampp/htdocs/phpsols/images/<?php echo $image; ?>">  <?php echo $image; ?></option> <?php } ?> </select> </p> <p> <input type="submit" name="create" id="create" value="Create Thumbnail"> </p> </form> The Win and Mac versions contain the fully qualified path to the images folder in default installations of XAMPP and MAMP. If necessary, change the path (highlighted in bold) to match your setup. When loaded into a browser, the drop-down menu should display the names of the photos in the images folder. This makes it easier to pick images quickly for testing. CHAPTER 8 218 Inside the upload_test folder that you created in Chapter 6, create a new folder called thumbs, and make sure it has the necessary permissions for PHP to write to it. Refer to “Establishing an upload directory” in Chapter 6 if you need to refresh your memory. Building the Ps2_Thumbnail class To generate a thumbnail image, the class needs to execute the following steps: 1. Get the dimensions of the original image. 2. Get the images MIME type. 3. Calculate the scaling ratio. 4. Create an image resource of the correct MIME type for the original image. 5. Create an image resource for the thumbnail. 6. Create the resized copy. 7. Save the resized copy to the destination folder using the correct MIME type. 8. Destroy the image resources to free memory. In addition to generating a thumbnail image, the class automatically inserts _thb before the filename extension, but a public method allows you to alter this value. The class also needs public methods to set the destination folder and the maximum size of the thumbnail, and to retrieve messages generated by the class. To keep the calculations simple, the maximum size controls only the larger of the thumbnails dimensions. Theres a lot to do, so Ill break up the code into sections. Theyre all part of the same class definition, but presenting the script this way should make it easier to understand, particularly if you want to use some of the code in a different context. PHP Solution 8-1: Getting the image details This PHP Solution describes how to get the dimensions and MIME type of the original image. 1. Create a new page called Thumbnail.php in the classes/Ps2 folder. The file will contain only PHP, so strip out any HTML code inserted by your editing program. 2. The class needs to keep track of quite a few properties. Begin the class definition by listing them like this: <?php class Ps2_Thumbnail { protected $_original; protected $_originalwidth; protected $_originalheight; protected $_thumbwidth; protected $_thumbheight; protected $_maxSize = 120; protected $_canProcess = false; protected $_imageType; GENERATING THUMBNAIL IMAGES 219 protected $_destination; protected $_name; protected $_suffix = '_thb'; protected $_messages = array(); } As in the Ps2_Upload class, all the properties have been declared as protected, which means they cant be changed accidentally outside the class definition. Again, I have followed the convention of beginning protected property names with an underscore. The names are descriptive, so they need little explanation. The $_maxSize property has been given a default value of 120 (pixels). This determines the maximum size of the thumbnails longer dimension. The $_canProcess Boolean is initially set to false. This is to prevent the script from attempting to process a file that isnt an image. The value will be reset to true if the MIME type matches that of an image. You can also use it to prevent the generation of a thumbnail if another error occurs. 3. The constructor takes one argument, the path to an image. Add the constructor definition after the list of protected properties, but inside the the closing curly brace: protected $_messages = array(); public function __construct($image) { if (is_file($image) && is_readable($image)) { $details = getimagesize($image); } else { $details = null; $this->_messages[] = "Cannot open $image."; } // if getimagesize() returns an array, it looks like an image if (is_array($details)) { $this->_original = $image; $this->_originalwidth = $details[0]; $this->_originalheight = $details[1]; // check the MIME type $this->checkType($details['mime']); } else { $this->_messages[] = "$image doesn't appear to be an image."; } } } The constructor begins with a conditional statement that checks that $image is a file and is readable. If it is, its passed to getimagesize() and the result is stored in $details. Otherwise, $details is set to null, and an error message is added to the $_messages property. When you pass an image to getimagesize(), it returns an array containing the following elements: CHAPTER 8 220 • 0: width (in pixels) • 1: height • 2: an integer indicating the type of image • 3: a string containing the correct width and height attributes ready for insertion in an <img> tag • mime: the images MIME type • channels: 3 for RGB, and 4 for CMYK images • bits: the number of bits for each color If the value passed as an argument to getimagesize() isnt an image, it returns false. Consequently, if $details is an array, you know youre dealing with an image. The images path is stored in the $_original property, and its width and height are stored in $_originalWidth and $_originalHeight respectively. However, the image might not be a suitable type, so the final check is to pass its MIME type to an internal method called checkType(), which youll define next. 4. The checkType() method compares the MIME type with an array of acceptable image types. If it finds a match, it resets the $_canProcess property to true, and stores the type in the $_imageType property. The method is used internally, so it needs to be declared as protected. Add the following code to the class definition: protected function checkType($mime) { $mimetypes = array('image/jpeg', 'image/png', 'image/gif'); if (in_array($mime, $mimetypes)) { $this->_canProcess = true; // extract the characters after 'image/' $this->_imageType = substr($mime, 6); } } There are many types of images, but only JPEG, PNG, and GIF are used in web pages, so the $_canProcess property is set to true only if the images MIME type matches one of those listed in the $mimetypes array. If the MIME type isnt in the list $_canProcess remains false, which later prevents the class from attempting to create a thumbnail. All image MIME types begin with image/. To make the value easier to use later, the substr() function extracts the characters after the slash and stores them in the $_imageType property. When used with two arguments, substr() starts at the position (counting from 0) specified in the second argument, and returns the rest of the string. 5. Its a good idea to test your code as you build the class. Catching errors early is much easier than hunting for a problem in a long script. To test the code, create a new public method called test() inside the class definition. . 'http://localhost/phpsols/error .php& apos;; // define the path to the download folder $filepath = 'C:/xampp/htdocs/phpsols/images/'; $getfile = NULL; // block any attempt to explore the filesystem. filesize($path); header('Content-Type: application/octet-stream'); header('Content-Length: '. $size); header('Content-Disposition: attachment; filename=' . $getfile);. header('Content-Transfer-Encoding: binary'); // open the file in read-only mode // suppress error messages if the file can't be opened $file = @fopen($path, 'r');

Ngày đăng: 06/07/2014, 19:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan