|
użytkowników online: 65
|
OPINIE UŻYTKOWNIKÓW
|
Przyznam, że jestem pod sporym wrażeniem. Od wielu lat zajmuje się grafiką przeznaczoną do druku ze szczególnym uwzględnieniem opakowań. Z radością stwierdzam, iż twórca serwisu jest moim ulubionym typem potencjalnego współpracownika (choć branża troszeczkę inna) tzn. pada pytanie i błyskawicznie pada konkretna odpowiedź bez względu na stopień skomplikowania pytania. Gorąco polecam współpracę, gdyż macie pewność że nie zostaniecie potraktowani sloganami typu "oczywiście", "nie ma sprawy" tylko otrzymacie konkretną pomoc. Tak trzymać! Na pewno jeszcze nie raz skorzystam
Paweł
Studio Gama
|
|
PODRĘCZNIK PHP 5.x, 4.x, 3.x - częściowo spolszczony / źródło: www.php.net
[Spis]
[A]
[B]
[C]
[D]
[E]
[F]
[G]
[H]
[I]
[J]
[K]
[L]
[M]
[N]
[O]
[P]
[Q]
[R]
[S]
[T]
[U]
[V]
[X]
[W]
[Z]
Rozdział 38. Handling file uploads
This feature lets people upload both text and binary files.
With PHP's authentication and file manipulation functions,
you have full control over who is allowed to upload and
what is to be done with the file once it has been uploaded.
PHP is capable of receiving file uploads from any RFC-1867
compliant browser (which includes Netscape Navigator 3
or later, Microsoft Internet Explorer 3
with a patch from Microsoft, or later without a patch).
PHP also supports PUT-method file uploads as used by
Netscape Composer and W3C's
Amaya clients. See the PUT Method
Support for more details.
Przykład 38-1. File Upload Form
A file upload screen can be built by creating a special form which
looks something like this:
<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
<!-- MAX_FILE_SIZE must precede the file input field -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Name of input element determines name in $_FILES array -->
Send this file: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form> |
The __URL__ in the above example should be replaced,
and point to a PHP file.
The MAX_FILE_SIZE hidden field (measured in bytes) must
precede the file input field, and its value is the maximum filesize accepted.
This is an advisory to the browser, PHP also checks it.
Fooling this setting on the browser side is quite easy, so never rely
on files with a greater size being blocked by this feature.
The PHP settings for maximum-size, however, cannot be fooled.
This form element should always be used as it
saves users the trouble of waiting for a big file being transferred only
to find that it was too big and the transfer failed.
|
Notatka:
Be sure your file upload form has attribute enctype="multipart/form-data"
otherwise the file upload will not work.
The global $_FILES
exists as of PHP 4.1.0 (Use $HTTP_POST_FILES
instead if using an earlier version).
These arrays will contain all the uploaded file information.
The contents of $_FILES
from the example form is as follows. Note that this assumes the use of
the file upload name userfile, as used in the example
script above. This can be any name.
- $_FILES['userfile']['name']
The original name of the file on the client machine.
- $_FILES['userfile']['type']
The mime type of the file, if the browser provided this
information. An example would be
"image/gif".
- $_FILES['userfile']['size']
The size, in bytes, of the uploaded file.
- $_FILES['userfile']['tmp_name']
The temporary filename of the file in which the uploaded file
was stored on the server.
- $_FILES['userfile']['error']
The error code
associated with this file upload. This element was added in PHP 4.2.0
Files will, by default be stored in the server's default temporary
directory, unless another location has been given with the upload_tmp_dir directive in
php.ini. The server's default directory can
be changed by setting the environment variable
TMPDIR in the environment in which PHP runs.
Setting it using putenv() from within a PHP
script will not work. This environment variable can also be used
to make sure that other operations are working on uploaded files,
as well.
Przykład 38-2. Validating file uploads
See also the function entries for is_uploaded_file()
and move_uploaded_file() for further information. The
following example will process the file upload that came from a form.
|
<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print_r($_FILES);
print "</pre>";
?>
|
|
The PHP script which receives the uploaded file should implement
whatever logic is necessary for determining what should be done
with the uploaded file. You can, for example, use the
$_FILES['userfile']['size'] variable
to throw away any files that are either too small or too big. You
could use the
$_FILES['userfile']['type'] variable
to throw away any files that didn't match a certain type criteria.
As of PHP 4.2.0, you could use $_FILES['userfile']['error']
and plan your logic according to the error codes.
Whatever the logic, you should either delete the file from the
temporary directory or move it elsewhere.
If no file is selected for upload in your form, PHP will return
$_FILES['userfile']['size'] as 0, and
$_FILES['userfile']['tmp_name'] as none.
The file will be deleted from the temporary directory at the end
of the request if it has not been moved away or renamed.
Przykład 38-3. Uploading array of files
PHP supports HTML array feature
even with files.
<form action="" method="post" enctype="multipart/form-data">
<p>Pictures:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</p>
</form> |
|
<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "data/$name");
}
}
?>
|
|
User Contributed Notesbrett dot r dot brown at gmail dot com
13-Jan-2006 12:01
In regards to geert dot php at myrosoft dot com about having the filenames cut off if single quotes are present in the filename, I had this same problem. The solution to this, is to set magic_quotes_gpc to off.
When magic_quotes_gpc is on, whenever a single quote is present in any _post data, a \ is inserted before any single quotes as an escape character. This comes in handy if you're storing the post data into mySQL, but causes problems, as you've had, when receiving an upload.
jason
10-Jan-2006 02:08
Regarding empty $_FILES and $_POST arrays when uploading files larger than post_max_size:
Tucked away in http://us3.php.net/manual/en/ini.core.php#ini.post-max-size is this nugget:
"If the size of post data is greater than post_max_size, the $_POST and $_FILES superglobals are empty. This can be tracked in various ways, e.g. by passing the $_GET variable to the script processing the data, i.e. <form action="edit.php?processed=1">, and then checking if $_GET['processed'] is set."
This may seem like a bug. You'd expect something like UPLOAD_ERR_FORM_SIZE to be set. But you just two empty superglobals.
I've seen it submitted to bugs.php.net twice and it's been marked as bogus both times.
Marcus
04-Jan-2006 04:11
Many ppl uses a java applet for uploading files instead of a forms post. This way you can get a progress bar etc.
If you for some reason cannot upload very large files you can use the java applet to upload it in chunks. I made a small change to the free JUpload applet hosted at sourceforge to do this.
If you in the url you're posting to add the argument
juchunksize=integervalue
the upload will be done as several posts where max-size of one part is integervalue. So you can keep track of where you are, two more parameters are added:
jupart, which is 0..
jufinal, which is 0 when there is more left or 1 if finished.
address to project:
http://sourceforge.net/projects/jupload
link to this JUpload version is here:
http://tinyurl.com/a2j7t
geert dot php at myrosoft dot com
23-Dec-2005 09:16
When file names do contain single quote parts of the filename are being lost.
eg.: uploading a filename
startName 'middlepart' endName.txt
will be uploaded (and hence stored in the _Files ['userfile'] variable as
endName.txt
skipping everything before the second single quote.
pete at NOSPAMpetesmithcomputers dot com
08-Dec-2005 02:03
I find I often have to handle photos in CMSs, so I wrote this class. It doubtless needs improvements, but it works pretty well.
<?php
class picture
{
var $save_dir; var $filename="spacer.gif"; var $error_message=""; var $width; var $height; function picture($save_directory, $file_array, $max_width, $max_height)
{
$this->save_dir = $save_directory;
$this->width = $max_width;
$this->height = $max_height;
$temp_filename = $file_array['name'];
$ext = explode('.',$temp_filename);
$ext = $ext[count($ext)-1];
$temp_filename = time().".".$ext;
if (preg_match('/^(gif|jpe?g)$/',$ext)) {
list($width_orig, $height_orig) = getimagesize($file_array['tmp_name']);
if ($this->width && ($width_orig < $height_orig)) {
$this->width = ($this->height / $height_orig) * $width_orig;
} else {
$this->height = ($this->width / $width_orig) * $height_orig;
}
$image_p = imagecreatetruecolor($this->width, $this->height);
if($ext=='gif'){
$image = imagecreatefromgif($file_array['tmp_name']);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $this->width, $this->height, $width_orig, $height_orig);
imagegif($image_p, $this->save_dir.$temp_filename, 80);
}
else
{
$image = imagecreatefromjpeg($file_array['tmp_name']);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $this->width, $this->height, $width_orig, $height_orig);
imagejpeg($image_p, $this->save_dir.$temp_filename, 80);
}
imagedestroy($image_p);
imagedestroy($image);
$this->filename=$temp_filename;
}else{
$this->error_message.="<br> file is not a jpeg or gif picture <br>";
}
}
}
?>
djot at hotmail dot com
27-Nov-2005 11:02
-
Be carefull with setting max_file_size via
ini_get('upload_max_filesize');
ini_get might return values like "2M" which will result in non working uploads.
This was the "no no" in my case:
$form = '<input type="hidden" name="MAX_FILE_SIZE" value=".ini_get('upload_max_filesize')." />';
Files were uploaded to the server, but than there was not any upload information, not even an error message. $_FILES was completly empty.
djot
-
info at giel berkers dot com
10-Nov-2005 01:03
I had problems when uploading files using Internet Explorer and Firefox. I checked for extension and mime-type to make sure it was a jpeg-file my users uploaded. Firefox did it well, only Internet Explorer failed to accept the file saying it wasn't the correct mime-type. After some testing, I discovered that Firefox reads the mime-type of a Jpeg-image as:
image/jpeg
While Internet Explorer reads it as:
image/pjpeg
I hope this helps somebody to avoid an evening debugging. To contribute to php.net, I enclosed my secure upload script for Jpeg files:
<?php
function storefile($var, $location, $filename=NULL, $maxfilesize=NULL) {
$ok = false;
$mime = $_FILES[$var]["type"];
if($mime=="image/jpeg" || $mime=="image/pjpeg") {
$name = $_FILES[$var]["name"];
$array = explode(".", $name);
$nr = count($array);
$ext = $array[$nr-1];
if($ext=="jpg" || $ext=="jpeg") {
$ok = true;
}
}
if(isset($maxfilesize)) {
if($_FILES[$var]["size"] > $maxfilesize) {
$ok = false;
}
}
if($ok==true) {
$tempname = $_FILES[$var]['tmp_name'];
if(isset($filename)) {
$uploadpath = $location.$filename;
} else {
$uploadpath = $location.$_FILES[$var]['name'];
}
if(is_uploaded_file($_FILES[$var]['tmp_name'])) {
while(move_uploaded_file($tempname, $uploadpath)) {
}
}
return true;
} else {
return false;
}
}
?>
You can use this script as follow:
<?
if(isset($_FILES['name'])) {
if(storefile("name", $_SERVER['DOCUMENT_ROOT']."test/img")) {
echo("Upload succeeded!");
} else {
echo("Upload failed...");
}
}
?>
The last 2 parameters 'filename' and 'maxfilesize' are optional. Offcourse, you can change this script with other mime types and extensions to fit your needs.
ohdotoh at randomnoisebursts dot com
10-Oct-2005 09:33
my quick and simple don't overwrite files that exist solution:
if (file_exists($sysfolder . '/' . $filename)) {
// append a digit to the beginning of the name
$tmpVar = 1;
while(file_exists($sysfolder . '/' . $tmpVar . '-' . $filename)) {
// and keep increasing it until we have a unique name
$tmpVar++;
}
$filename= $tmpVar . '-' . $filename;
}
ded at in dot ua
04-Oct-2005 11:03
Generally, if you use
CharsetDisable on
or
CharsetSourceEnc off
in (russian) apache config file, and if your script which receives upload still have some html, use <meta http-equiv ...> tags so browser can correctly display the pages.
andrea at 3site dot it
21-Sep-2005 05:05
NO_lewis_SPAM at NOSPAM dot delta-hf dot co dot uk
03-Sep-2005 06:27
I have been having issues with putting data in to an MSSQL database from an uploaded file. Trying to INSERT a file in excess of 25MB caused "Insufficient memory" errors from the SQL server
I decided to chunk the data into the database rather than trying to spurt it all in at once. The memory management is much better and from Submit to in the DB takes about 1 second per MB. The machine has dual Pentium 3 933MHz and 2GB RAM.
First things first I had to write a stored procedure. I saw no point in attempting to return a TEXTPTR(), which is required for the UPDATETEXT function to work, back to PHP so I didn't even bother. This is my very first stored procedure since this is really the first time I've developed solely for MSSQL. The important thing is that it's functional.
Here's the code I used for my stored procedure. After writing this I need to execute it in a loop to get all the data in, in the correct order. I leave that bit to PHP of course. Please don't tell me I could have just written it all in the stored procedure using another language, this is PHP and MSSQL we're talking about. :)
The zipfile column data type is TEXT, I tried IMAGE but it was problematic dealing with HEX data.
///////////// SP//////////////////////
CREATE PROCEDURE dbo.dds_writeBlob @dataChunk AS TEXT, @refCode AS VARCHAR(50), @offSet AS INT
AS
DECLARE @dataPtr AS BINARY(16)
SELECT @dataPtr=TEXTPTR(zipfile)
FROM [dbo].[file] (UPDLOCK)
WHERE [dbo].[file].ref = @refCode
UPDATETEXT [dbo].[file].zipfile @dataPtr @offSet 0 @dataChunk
GO
//////////////////END SP/////////////////
Then of course comes the PHP code to do the chunking. Firstly I have to convert the binary data to a type that can be accepted by TEXT data type. base64_encode() comes in handy for this purpose but of course I need it in chunks so I used chunk_split() and split it in to chunks of 256000 bytes by declaring the optional [chunklen]. I then explode() it in to a numerically indexed array using the newlines ("\r\n") that are inserted every [chunklen] by chunk_split. I can then loop through with a for(), passing the data chunks, in order, one at a time to the stored procedure. Here's the code:
<?
$data = chunk_split(base64_encode(fread(fopen($file, "rb"), filesize($file))), 256000);
$arrData = explode("\r\n", $data);
unset($data); $num = count($arrData);
$offset = 0;
for ($i=0;$i<$num;$i++) {
$buffer = $arrData[$i];
$query = "EXEC [dds_writeBlob] '".$buffer."', '$reference', $offset";
@mssql_query($query) or die(mssql_get_last_message());
$offset = ($offset + strlen($buffer));
}
?>
Of course we then need to extract the data from the database. This, thankfully, is a lot easier! Simply base64_decode() the data before outputting to a browser.
<?
$query = "SELECT zipfile, job_code FROM [file] WHERE ref = '$ref'";
@$result = mssql_query($query) or die('File Download: Failed to get file from the database.');
$file = mssql_fetch_assoc($result);
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="job-'.trim($file['job_code']).'.zip"');
echo base64_decode($file['zipfile']);
?>
The benefit of storing in base64_encoded format is the simplicity with which you can now send mime emails with the data attached as an alternative to having people download it. A simple chunk_split() on the SELECTed data will have it in the right format for mime mails.
The draw back is the extra size required! Expect the base64_encoded data to be 1.33 times the size of the original data!
Dave Koopman
25-Aug-2005 04:22
mariodivece at bytedive dot com
24-Aug-2005 08:33
Just wanted to point out a detail that might be of interest to some:
when using base64_encode to store binary data in a database, you are increasing the size of the data by 1.33 times. There is a nicer way of storing the data directly. Try the following:
<?php $data = mysql_real_escape_string($data); ?>
This will leave the data untouched and formatted in the correct way and ready to be inserted right into a MySQL statement without wasting space.
By the way, I'd like to thank therebechips for his excellent advice on data chunks.
warwickbarnes at yahoo dot co dot uk
19-Aug-2005 01:58
You may come across the following problem using PHP on Microsoft IIS: getting permission denied errors from the move_uploaded_file function even when all the folder permissions seem correct. I had to set the following to get it to work:
1. Write permissions on the the folder through the IIS management console.
2. Write permissions to IUSR_'server' in the folder's security settings.
3. Write permissions to "Domain Users" in the folder's security settings.
The third setting was required because my application itself lives in a secure folder - using authentication (either Basic or Windows Integrated) to identify the users. When the uploads happen IIS seems to be checking that these users have write access to the folder, not just whether the web server (IUSR_'server') has access.
Also, remember to set "Execute Permissions" to "None" in the IIS management console, so that people can't upload a script file and then run it. (Other checks of the uploaded file are recommended as well but 'Execute None' is a good start.)
myko AT blue needle DOT com
16-Aug-2005 06:13
Just a quick note that there's an issue with Apache, the MAX_FILE_SIZE hidden form field, and zlib.output_compression = On. Seems that the browser continues to post up the entire file, even though PHP throws the MAX_FILE_SIZE error properly. Turning zlib compression to OFF seems to solve the issue. Don't have time to dig in and see who's at fault, but wanted to save others the hassle of banging their head on this one.
muoihv at 1yt dot net
04-Aug-2005 10:47
// Split file Submit and HTML post
<?
$num_of_uploads=3;
$file_types_array=array("JPG");
$max_file_size=1048576;
$upload_dir="D:\AppServ\www";
function uploaderFILES($num_of_uploads=1, $file_types_array=array("JPG"), $max_file_size=1048576, $upload_dir=""){
if(!is_numeric($max_file_size)){
$max_file_size = 1048576;
}
foreach($_FILES["file"]["error"] as $key => $value)
{
if($_FILES["file"]["name"][$key]!="")
{
if($value==UPLOAD_ERR_OK)
{
$origfilename = $_FILES["file"]["name"][$key];
$filename = explode(".", $_FILES["file"]["name"][$key]);
$filenameext = $filename[count($filename)-1];
unset($filename[count($filename)-1]);
$filename = implode(".", $filename);
$filename = substr($filename, 0, 15).".".$filenameext;
$file_ext_allow = FALSE;
for($x=0;$x<count($file_types_array);$x++){
if($filenameext==$file_types_array[$x])
{
$file_ext_allow = TRUE;
}
} if($file_ext_allow){
if($_FILES["file"]["size"][$key]<$max_file_size){
if(move_uploaded_file($_FILES["file"]["tmp_name"][$key], $upload_dir.$filename)){
echo("File uploaded successfully. - <a href='".$upload_dir.$filename."' target='_blank'>".$filename."</a><br />");
}
else { echo('<font color="#FF0000">'.$origfilename."</font> was not successfully uploaded - khong the upload duoc <br />");}
}
else { echo('<font color="#FF0000">'.$origfilename."</font> was too big, not uploaded - Kich thuoc file qua' lon <br />"); }
} else{ echo('<font color="#FF0000">'.$origfilename." </font>had an invalid file extension, not uploaded - File nay khong ton tai <br />"); }
}
else{ echo('<font color="#FF0000">'.$origfilename." </font>was not successfully uploaded - khong the upload duoc <br />"); } }
}
} ?>
<form action='<?=$PHP_SELF;?>' method='post' enctype='multipart/form-data'>Upload files:<br /><input type='hidden' name='submitted' value='TRUE' id='<?=time();?>' >
<input type='hidden' name='MAX_FILE_SIZE' value='<?=$max_file_size;?>' >
<? for($x=0;$x<$num_of_uploads;$x++){
$form .= "<input type='file' name='file[]'><br />";
}
$form .= "<input type='submit' value='Upload'><br />
<font color='red'>*</font>Maximum file length (minus extension) is 15 characters. Anything over that will be cut to only 15 characters. Valid file type(s): ";
for($x=0;$x<count($file_types_array);$x++){
if($x<count($file_types_array)-1){
$form .= $file_types_array[$x].", ";
}else{
$form .= $file_types_array[$x].".";
}
}
echo($form);
?>
</form>
//////////////////////////////////////
<?
if(isset($_POST["submitted"])){
uploaderFILES($num_of_uploads, $file_types_array, $max_file_size, $upload_dir);
}
?>
dan at DLC2 dot com
01-Aug-2005 10:19
Are you struggling to implement these code samples for "file upload" or "multiple file upload"? Are you still scratching your head why they don't work??
I tried everything, until I realized that my version of PHP was too old! Look at these tidbits (collected from pages at PHP.NET for your enjoyment):
Requires PHP v4.1 - The $_FILES array
Requires PHP v4.2 - The "error" sub-array - example: $_FILES["userfile"]["error"]
Requires PHP v4.3 - The constants for "error" sub-array - example: UPLOAD_ERR_OK (value 0)
So, if you have PHP v4.0.X or earlier, use the $HTTP_POST_FILES variable and just do without the error sub-array and it
|