Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 30 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
30
Dung lượng
610,35 KB
Nội dung
Chapter 7: Manipulating and Creating Images with PHP 181 (“’ . $image_caption . ‘”, “’ . $image_username . ‘”, “’ . $image_date . ‘”)’; $result = mysql_query($query, $db) or die (mysql_error($db)); //retrieve the image_id that MySQL generated automatically when we inserted //the new record $last_id = mysql_insert_id(); //because the id is unique, we can use it as the image name as well to make //sure we don’t overwrite another image that already exists $imagename = $last_id . $ext; // update the image table now that the final filename is known. $query = ‘UPDATE images SET image_filename = “’ . $imagename . ‘” WHERE image_id = ‘ . $last_id; $result = mysql_query($query, $db) or die (mysql_error($db)); //save the image to its final destination switch ($type) { case IMAGETYPE_GIF: imagegif($image, $dir . ‘/’ . $imagename); break; case IMAGETYPE_JPEG: imagejpeg($image, $dir . ‘/’ . $imagename, 100); break; case IMAGETYPE_PNG: imagepng($image, $dir . ‘/’ . $imagename); break; } imagedestroy($image); ? > < html > < head > < title > Here is your pic! < /title > < /head > < body > < h1 > So how does it feel to be famous? < /h1 > < p > Here is the picture you just uploaded to our servers: < /p > < img src=”images/ < ?php echo $imagename; ? > ” style=”float:left;” > < table > < tr > < td > Image Saved as: < /td > < td > < ?php echo $imagename; ? > < /td > < /tr > < tr > < td > Image Type: < /td > < td > < ?php echo $ext; ? > < /td > < /tr > < tr > < td > Height: < /td > < td > < ?php echo $height; ? > < /td > < /tr > < tr > < td > Width: < /td > < td > < ?php echo $width; ? > < /td > < /tr > < tr > < td > Upload Date: < /td > < td > < ?php echo $image_date; ? > < /td > < /tr > < /table > < /body > < /html > 7. Save this file as check_image.php . 8. Now open upload_image.html in your browser. The page will load, and your screen should look like Figure 7 - 2 . c07.indd 181c07.indd 181 12/10/08 6:01:11 PM12/10/08 6:01:11 PM Part I: Movie Review Web Site 182 9. Upload your image. Your page should now look something like Figure 7 - 3 . Figure 7-2 Figure 7-3 c07.indd 182c07.indd 182 12/10/08 6:01:11 PM12/10/08 6:01:11 PM Chapter 7: Manipulating and Creating Images with PHP 183 How It Works In upload_image.html , you have given the HTML form the ability to accept files simply by doing two things. The first is using the file type input element. The input element now displays a Browse button next to the text area, which allows a visitor to surf his or her local disk and populate the field with the file ’ s path. The second is specifying the form ’ s enctype attribute to multipart/form - data . Providing this attribute is necessary for the file to transfer correctly. < form action=”check_image.php” method=”post” enctype=”multipart/form-data” > < td > Upload Image* < /td > < td > < input type=”file” name=”uploadfile” / > < /td > Keep in mind that the form element ’ s method attribute should be set to post as well. Some browsers support the put method for transfers as well, and if you need to use this, then you ’ ll want to read the PHP manual at http://www.php.net/manual/en/features.file - upload.put - method.php . Either way, image transfers will not work with get . There is much more going on in check_image.php . A cursory overview shows that the script first connects to MySQL and selects the moviesite database. It makes sure a file was uploaded correctly and that it is one of the allowed file types. It then stores the picture ’ s information into the database. Finally, the script saves a copy of the uploaded image to its permanent location in the filesystem and outputs a summary back to the visitor. If the process breaks down at any point for any reason (the user doesn ’ t upload a file, or the file is an invalid file type for example), then PHP stops its processing and displays an error message. You can use several different methodologies when dealing with images. For example, if you think you will have numerous files for each user, you can create a directory for each user and store each image within it. On the other hand, a single directory for storing the images might be a better choice if you are planning to allow only one image file to be uploaded. In this instance, you are keeping all the image files in one directory just for the sake of simplicity. Regardless of the structure you choose, you must apply some checks for duplicate filenames, so files that have already been uploaded aren ’ t overwritten. In this case, you renamed each incoming file the same name as the unique ID assigned to it. This ensures that each file will have its own unique name and you won ’ t have any problems if two users upload a file with the same name. PHP stores information about recently uploaded files in the $_FILES array. The array has multiple levels, and the first key is the name you assigned to the form ’ s image field. So, because the field ’ s definition in upload_image.html was this: < input type=”file” name=”uploadfile” / > then information about the file will be available in createimages.php in $_FILES[‘uploadfile’] . This way, you can access the correct file if you have been allowing multiple images to be uploaded. For example, let ’ s say you were working with a form that had the following: < input type=”file” name=”uploadfile1” / > < br/ > < input type=”file” name=”uploadfile2” / > < br/ > < input type=”file” name=”uploadfile3” / > You would then have $_FILES[‘uploadfile1 ’ ] , $_FILES[‘uploadfile2 ’ ] , and $_FILES[‘uploadfile3 ’ ] . c07.indd 183c07.indd 183 12/10/08 6:01:12 PM12/10/08 6:01:12 PM Part I: Movie Review Web Site 184 The next level of the $_FILES array is information about the uploaded file. Possible keys are: name: References the name of the file as it was on the user ’ s local machine . type: Stores the file ’ s MIME type as provided by the browser . size : The size of the uploaded file in bytes . tmp_name: The name of the uploaded file on the server . error : The error code associated with the file transfer . The file is transferred from the visitor ’ s computer up to the server and is stored as a temporary file. The temporary file is deleted after the receiving script finishes executing. This is very important to remember because if you do not somehow move the temporary file to a more permanent location in the filesystem in the processing script, then the uploaded file will be lost forever. The name key holds the name of the original file on the local machine. The tmp_name key holds the name of the temporary copy of the file on the server. The type key holds the MIME type of the uploaded file, for example image/jpg or image/gif . But this value is set by the browser and may not be correct. So while it ’ s provided to you for convenience, you must also realize that PHP doesn ’ t check the value for accuracy, and you mustn ’ t depend too much on it. A malicious user could fake the type value and cause you headaches. The size key holds the size of the uploaded file. The file size is represented in bytes, so a 15K file would have a value here of 15,360. The error key holds the error code associated with the file upload. It holds a numeric value, but PHP also has predefined constants to represent the value, and using these constants makes your script easier to read and manage. These constants are: UPLOAD_ERR_OK : The file uploaded successfully and there is no error. UPLOAD_ERR_INI: The size of the uploaded file exceeds the upload_max_filesize directive set in php.ini . UPLOAD_ERR_FORM_SIZE : The size of the uploaded file exceeded the MAX_FILE_SIZE directive set in the HTML form. UPLOAD_ERR_PARTIAL : The file was only partially uploaded and is not complete. UPLOAD_ERR_NO_FILE : The user did not upload a file. UPLOAD_ERR_NO_TMP_DIR : The temporary directory on the server to which the file is initially uploaded is missing. UPLOAD_ERR_CANT_WRITE : The temporary directory exists on the server, but PHP cannot write to it. UPLOAD_ERR_EXTENSION : The file upload was stopped by a PHP extension. There are a handful of places where you can provide restrictions on file uploading, and they are related to UPLOAD_ERR_INI , UPLOAD_ERR_FORM_SIZE , and UPLOAD_ERR_EXTENSION . ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ c07.indd 184c07.indd 184 12/10/08 6:01:12 PM12/10/08 6:01:12 PM Chapter 7: Manipulating and Creating Images with PHP 185 The UPLOAD_ERR_INI value is returned when the size of the uploaded file exceeds the upload_max_ filesize directive set in the php.ini configuration file. By default, this directive is set to 2 megabytes: upload_max_filesize = 2M Depending on the type and size of files your PHP application is designed to transfer, you may want to change this value, especially for pictures, as the resolution of digital cameras keep increasing. If you do change this, then you should also look at the post_max_size directive in php.ini. While upload_max_filesize limits the size of a file upload, post_max_size limits the size of an entire post transaction. An uploaded file is only part of the form data that gets posted by upload_image .html , so if upload_max_filesize is set larger than upload_post_max_size , then the upload transfer could still fail. Between these two directives, you can impose a hard limit on the maximum amount of data that can be received by PHP. The UPLOAD_ERR_FORM_SIZE value is returned when the uploaded file exceeds the size set by a special hidden field in the HTML form. Here is the form from upload_image.html , with the added hidden field labeled MAX_FILE_SIZE : < form action=”check_image.php” method=”post” enctype=”multipart/form-data” > < table > < tr > < td > Your Username < /td > < td > < input type=”text” name=”username” / > < /td > < /tr > < td > Upload Image* < /td > < td > < input type=”hidden” name=”MAX_FILE_SIZE” value=”262144”/ > < input type=”file” name=”uploadfile” / > < /td > < /tr > < tr > < td colspan=”2” > < small > < em > * Acceptable image formats include: GIF, JPG/JPEG and PNG. < /em > < /small > < /td > < /tr > < tr > < td > Image Caption < br/ > < /td > < td > < input type=”text” name=”caption” / > < /td > < /tr > < tr > < td colspan=”2” style=”text-align: center” > < input type=”submit” value=”Submit”/ > < /td > < /tr > < /table > < /form > MAX_FILE_SIZE should appear before the file input field. It does not set a hard limit, as the php.ini directives do, because someone could modify the field ’ s value before posting the form ’ s data, but it is still useful as a convenience. The idea is that the server can stop receiving the file once this limit is reached, and PHP can start formulating its response once it has decided the size is greater than what is allowed. The user doesn ’ t have to wait for the entire file to upload just to see a “ file is too large ” error. I tend to avoid using MAX_FILE_SIZE because there is some debate over the ultimate usefulness of c07.indd 185c07.indd 185 12/10/08 6:01:13 PM12/10/08 6:01:13 PM Part I: Movie Review Web Site 186 MAX_FILE_SIZE , based on browser support and the fact that it only imposes a soft limit. But feel free to experiment with it and formulate your own usage preference. After the script sees that the file upload was successful, the getimagesize() function is used to retrieve some information about it (we ’ ve always thought that perhaps the function would be better named getimageinfo() because it returns more than just the image ’ s size, but we digress . . . ). It returns an array with 5 elements: 0 : The image ’ s width measured in pixels . 1 : The image ’ s height measured in pixels . 2 : A numeric value identifying the file ’ s image type . 3 : A string like height= “ yyy ” width= “ xxx ” that can be used to include in an HTML img tag . 4 : A string corresponding to the MIME type of the image . While integers are efficient for computers to work with, they aren ’ t always easier for human beings to work with or remember. So PHP offers predefined constants that match up with the numeric value identifying the file ’ s image type returned by index 2. They are: IMAGETYPE_GIF: Returned for GIF images (MIME type image/gif ) . IMAGETYPE_JPEG: Returned for JPEG files (MIME type image/jpeg ) . IMAGETYPE_PNG: Returned for PNG files (MIME type image/png ) . IMAGETYPE_SWF: Returned for SWF files (MIME type application/x - shockwave - flash ) . IMAGETYPE_PSD : Returned for Photoshop format files (MIME type image/psd ) . IMAGETYPE_BMP: Returned for bitmap files (MIME type image/bmp ) . IMAGETYPE_TIFF_II: Returned for TIFF files using little - endian/Intel byte order encoding (MIME type image/tiff ) . IMAGETYPE_TIFF_MM : Returned for TIFF files using big - endian/Motorola byte order encoding (MIME type image/tiff ) . IMAGETYPE_JPC: Returned for JPEG2000 code stream files (MIME type application/octet - stream ) . IMAGETYPE_JP2: Returned for JPEG2000 JP2 files (MIME type image/jp2 ) . IMAGETYPE_JPX : Returned for JPEG2000 JPX files (MIME type application/octet - stream ) . IMAGETYPE_JB2: Returned for JBIG2 bitmap files (MIME type application/octet - stream ) . IMAGETYPE_SWC : Returned for Flash Component Distribution files (MIME type application/x - shockwave - flash ) . IMAGETYPE_IFF: Returned for Amiga bitmap files (MIME type image/iff ) . IMAGETYPE_WBMP: Returned for Wireless Bitmap files (MIME type image/vnd.wap.wbmp ) . IMAGETYPE_XBM : Returned for X Bitmap graphic files (MIME type image/xbm ) . IMAGETYPE_ICO : Returned for icon files (MIME type image/vnd.microsoft.icon ) . ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ ❑ c07.indd 186c07.indd 186 12/10/08 6:01:13 PM12/10/08 6:01:13 PM Chapter 7: Manipulating and Creating Images with PHP 187 Note that WBMP is not the same type of file as a Windows bitmap (BMP). WBMP files are Wireless Bitmap files, used in Palm Pilots and other compact wireless devices. The PHP/GD combo does not provide for direct manipulation of BMP files. If you need to work with BMP files, you may want to take a look at the ImageCreateFromBMP and ImageBMP library classes at www.jpexs.com/php.html or use the imagick PECL extension at http://pecl.php.net/package/imagick . After the script determines the type of image that was uploaded, it reads the file into memory. The imagecreatefrom*() function opens an image file and returns a resource handle so you can work with it. Remember that the file is first uploaded to a temporary location, and it is then your responsibility as a programmer to move it to a more permanent location before it is lost forever. Typically, you would use the move_uploaded_file() for this. The first parameter to move_ uploaded_files() is the temporary filename, and the second is the permanent location, like this: move_uploaded_file($_FILES[‘upload_file’][‘tmp_name’], $dir . ‘/’ . $_FILES[‘upload_file’][‘name’]); And in most cases this is fine. However, as an extra precaution, we have chosen to load the image file into memory using the correct function and then rewrite it out to a new file at the target location in the images directory. This acts as an extra check to make sure the uploaded image is a valid image file of the type it ’ s claimed to be, because the imagecreatefrom*() function will fail if the format is invalid. At the same time, you assign the file extension based on the file type, since you will need to have that information available when you resave your file. If the uploaded file doesn ’ t match any of your cases, the default is applied. The default action is that the reader will see the “ The file you uploaded was not a supported filetype. ” message. This all helps you to filter out unacceptable file types, non - image files, or corrupted files that have been uploaded. Assuming everything is going smoothly, you can then insert the information in the table, with the following lines: //insert info into image table $query = ‘INSERT INTO images (image_caption, image_username, image_date) VALUES (“’ . $image_caption . ‘”, “’ . $image_username . ‘”, “’ . $image_date . ‘”)’; $result = mysql_query($query, $db) or die (mysql_error($db)); //retrieve the image_id that MySQL generated automatically when we inserted //the new record $last_id = mysql_insert_id(); //because the id is unique, we can use it as the image name as well to make //sure we don’t overwrite another image that already exists $imagename = $last_id . $ext; // update the image table now that the final filename is known. $query = ‘UPDATE images SET image_filename = “’ . $imagename . ‘” WHERE image_id = ‘ . $last_id; $result = mysql_query($query, $db) or die (mysql_error($db)); c07.indd 187c07.indd 187 12/10/08 6:01:14 PM12/10/08 6:01:14 PM Part I: Movie Review Web Site 188 Initially, you do not know what the name of the file will be as it is saved on disk, because the filename is based on the image record ’ s primary key, which is automatically assigned by MySQL. Therefore, the first query inserts the information that you do know — the image ’ s caption, the user ’ s username, and the current date. Once the record is created, you use the mysql_insert_id() function to find out what value MySQL assigned as the key. That knowledge then allows you to update the record and set the image ’ s filename correctly. You then write the image file to the images directory, with the following code: // save the image to its final destination switch ($type) { case IMAGETYPE_GIF: imagegif($image, $dir . ‘/’ . $imagename); break; case IMAGETYPE_JPEG: imagegif($image, $dir . ‘/’ . $imagename, 100); break; case IMAGETYPE_PNG: imagepng($image, $dir . ‘/’ . $imagename); break; } imagedestroy($image); Here, each of the functions imagegif() , imagejpeg() , and imagepng() writes the image data accessible by the $image resource to the specified filename. The imagejpeg() function also accepts an optional third parameter, which affects the image quality of the file because of compression. A value of 100 means you desire 100% quality with minimal compression, whereas 0 would give the least visual quality, but the highest image compression would be used, for a smaller file size on disk. The imagedestroy() function simply takes the $image resource and frees the memory used to load the original image. PHP will automatically clean up used memory and open resources when the execution of your script has completed, but still it ’ s considered a good practice to explicitly write this code in yourself. Finally, in the HTML portion of the script, you simply spit the picture back out to the user, so he or she can see that the image was successfully uploaded. Converting Image File Types Is issuing the second query to the database to update the filename really necessary? Not really, but we set up the initial database code and PHP script to bring us to this point. PHP can use GD to convert image types from one format to another quite easily. If you were to allow image uploads in GIF, JPEG, or PNG formats but save them to the images directory as JPEG images, then you would no longer need the filename column in the database table, and you could streamline the check_image.php script. c07.indd 188c07.indd 188 12/10/08 6:01:14 PM12/10/08 6:01:14 PM Chapter 7: Manipulating and Creating Images with PHP 189 Try It Out Streamlining the Process Let ’ s make a few changes that not only highlight how to convert between image types but also will streamline our code. 1. Open your text editor, and enter the following code: < ?php $db = mysql_connect(‘localhost’, ‘bp6am’, ‘bp6ampass’) or die (‘Unable to connect. Check your connection parameters.’); mysql_select_db(‘moviesite’, $db) or die(mysql_error($db)); //create the images table $query = ‘ALTER TABLE images DROP COLUMN image_filename’; mysql_query($query, $db) or die (mysql_error($db)); echo ‘Images table successfully updated.’; ? > 2. Save your work as db_ch07 - 2.php . Open the file in a web browser now, and you see a message that the images table was successfully modified. 3. Make the following changes to the code in check_image.php (as highlighted): < ?php $db = mysql_connect(‘localhost’, ‘bp6am’, ‘bp6ampass’) or die (‘Unable to connect. Check your connection parameters.’); mysql_select_db(‘moviesite’, $db) or die(mysql_error($db)); //change this path to match your images directory $dir =’C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/images’; //make sure the uploaded file transfer was successful if ($_FILES[‘uploadfile’][‘error’] != UPLOAD_ERR_OK) { switch ($_FILES[‘uploadfile’][‘error’]) { case UPLOAD_ERR_INI_SIZE: die(‘The uploaded file exceeds the upload_max_filesize directive ‘ . ‘in php.ini.’); break; case UPLOAD_ERR_FORM_SIZE: die(‘The uploaded file exceeds the MAX_FILE_SIZE directive that ‘ . ‘was specified in the HTML form.’); break; case UPLOAD_ERR_PARTIAL: die(‘The uploaded file was only partially uploaded.’); break; case UPLOAD_ERR_NO_FILE: die(‘No file was uploaded.’); break; case UPLOAD_ERR_NO_TMP_DIR: die(‘The server is missing a temporary folder.’); break; c07.indd 189c07.indd 189 12/10/08 6:01:14 PM12/10/08 6:01:14 PM Part I: Movie Review Web Site 190 case UPLOAD_ERR_CANT_WRITE: die(‘The server failed to write the uploaded file to disk.’); break; case UPLOAD_ERR_EXTENSION: die(‘File upload stopped by extension.’); break; } } //get info about the image being uploaded $image_caption = $_POST[‘caption’]; $image_username = $_POST[‘username’]; $image_date = date(‘Y-m-d’); list($width, $height, $type, $attr) = getimagesize($_FILES[‘uploadfile’][‘tmp_name’]); // make sure the uploaded file is really a supported image // delete these lines switch ($type) { case IMAGETYPE_GIF: $image = imagecreatefromgif($_FILES[‘uploadfile’][‘tmp_name’]) or die(‘The file you uploaded was not a supported filetype.’); $ext = ‘.gif’; break; case IMAGETYPE_JPEG: $image = imagecreatefromjpeg($_FILES[‘uploadfile’][‘tmp_name’]) or die(‘The file you uploaded was not a supported filetype.’); $ext = ‘.jpg’; break; case IMAGETYPE_PNG: $image = imagecreatefrompng($_FILES[‘uploadfile’][‘tmp_name’]) or die(‘The file you uploaded was not a supported filetype.’); $ext = ‘.png’; break; default: die(‘The file you uploaded was not a supported filetype.’); } // end deleted lines $error = ‘The file you uploaded was not a supported filetype.’; switch ($type) { case IMAGETYPE_GIF: $image = imagecreatefromgif($_FILES[‘uploadfile’][‘tmp_name’]) or die($error); break; case IMAGETYPE_JPEG: $image = imagecreatefromjpeg($_FILES[‘uploadfile’][‘tmp_name’]) or die($error); break; case IMAGETYPE_PNG: $image = imagecreatefrompng($_FILES[‘uploadfile’][‘tmp_name’]) or c07.indd 190c07.indd 190 12/10/08 6:01:15 PM12/10/08 6:01:15 PM [...]... (image_caption, image_username, image_date) VALUES (“’ $image_caption ‘”, “’ $image_username ‘”, “’ $image_date ‘”)’; $result = mysql_ query($query, $db) or die (mysql_ error($db)); //retrieve the image_id that MySQL generated automatically when we inserted //the new record $last_id = mysql_ insert_id(); // delete these lines //because the id is unique, we can use it as the image name as well to make //sure... (image_caption, image_username, image_date) VALUES (“’ $image_caption ‘”, “’ $image_username ‘”, “’ $image_date ‘”)’; $result = mysql_ query($query, $db) or die (mysql_ error($db)); //retrieve the image_id that MySQL generated automatically when we inserted //the new record $last_id = mysql_ insert_id(); // delete these lines // save the image to its final destination $imagename = $last_id ‘.jpg’; imagejpeg($image,... will be minor changes 1 Open the check_image.php file, and make the following highlighted changes: . ‘”)’; $result = mysql_ query($query, $db) or die (mysql_ error($db)); //retrieve the image_id that MySQL generated automatically when we inserted //the new record $last_id = mysql_ insert_id(); . ‘”)’; $result = mysql_ query($query, $db) or die (mysql_ error($db)); //retrieve the image_id that MySQL generated automatically when we inserted //the new record $last_id = mysql_ insert_id(); . ‘”)’; $result = mysql_ query($query, $db) or die (mysql_ error($db)); //retrieve the image_id that MySQL generated automatically when we inserted //the new record $last_id = mysql_ insert_id();