Section 9.2. Files and Streams

9.2. Files and Streams

Accessing files has changed drastically. Prior to PHP 4.3.0, each type of file (local, compressed, remote) had a different implementation. However, with the introduction of streams, every interaction with a file makes use of the streams layer, a layer that abstracts access to the implementation details of a specific kind of "file." The streams layer makes it possible to create a GD image object from an HTTP source with a URL stream, work with compressed files, or copy a file from one file to another. You can apply your own conversions during the copy process by implementing a user-stream or filter.

9.2.1. File Access

Let's begin with the basic file-accessing functions. Originally, those functions only worked on normal files, so their names begin with "f," but PHP extends this to almost everything. The most used functions for file access are

  • fopen(). Opens a handle to a local file, or a file from an URL

  • fread(). Reads a block of data from a file

  • fgets(). Reads one single line from a file

  • fwrite() / fputs(). Writes a block of data to a file

  • fclose(). Closes the opened file handle

  • feof(). Returns true when the end of the file has been reached

Working with files is easy, as the following example shows:

 <?php     /* Open a file */     $fp = fopen ('data.dat',  'r');     if (!$fp) {         die ("The file could not be opened.");     }     /* Read a line from the file */     $line = fgets($fp);     /* Close the file handle */     fclose($fp); ?> 

In line 3, a file handle ($fp) is associated with the stream and the stream is associated with the counter.dat file that is on disk. The first parameter is the path to the file. The second parameter passed to fopen() is the mode. The mode specifies whether a stream is opened for reading, writing, both reading and writing, or appending. The following modes exist:

  • r. Opens the stream in read-only mode. The file pointer is placed at the beginning of the stream.

  • r+. Opens the stream for reading and writing. The file pointer is placed at the beginning of the stream.

  • w. Opens the stream in write-only mode. The file is cleared and the file pointer is placed at the beginning of the stream. If the file does not exist, an attempt is made to create the file.

  • w+. Opens the stream for reading and writing. The file is cleared and the file pointer is placed at the beginning of the stream. If the file does not exist, an attempt is made to create the file.

  • a. Opens in write-only mode. The file pointer is placed at the end of the stream. If the file does not exist, an attempt is made to create the file.

  • a+. Opens for reading and writing. The file pointer is placed at the end of stream. If the file does not exist, an attempt is made to create it.

The b modifier can be used with the mode to specify that the file is binary. Windows systems differentiate between text and binary files; if you don't use the b modifier for binary files in Windows, your file may become corrupted. Consequently, to make your scripts portable to Windows, it's wise to always use the b modifier when you work on a binary file, even when you are developing code on an operating system that doesn't require it. On UNIX OSs (Linux, FreeBSD, MacOSX, and so on), the b modifier has no effect whatsoever.

Here's another small example:

 <?php     /* Open a file in read/write mode and binary mode, and place      * the stream pointer at the beginning of the stream. */     $fp = fopen("/tmp/tempfile", "rb+");     /* Try to read a block of 4096 bytes from the file */     $block = fread($fp, 4096);     /* Write that same block of data to the stream again      * just after the first one */     fwrite($fp, $block);     /* Close the stream */     fclose($fp); ?> 

A third optional parameter, true, is available for fopen() that tells PHP to look in your include path for the file. The following script first tries to open php.ini (in read-only mode) from /etc, then from /usr/local/etc, and finally from the current directory (the dot in the path specifies the current directory). Because php.ini is not a binary file, we do not use the b modifier for the mode:

 <?php     /* Set the include path */     ini_set('include_path', '/etc:/usr/local/etc:.');     /* Open handle to file */     $fp = fopen('php.ini', 'r', TRUE);     /* Read all lines and print them */     while (!feof($fp)) {         $line = trim(fgets($fp, 256));         echo ">$line<\n";     }     /* Close the stream handle */     fclose($fp); ?> 

This script uses feof(), which is a function we haven't seen before. feof() tests whether the end of a file has been reached during the last fread() or fgets() call. We use fgets() here, with 256 as the second parameter. This number specifies the maximum length if the line that fgets() reads. It is important to choose this size carefully. PHP allocates this memory before reading, so if you use a value of 1,000,000, PHP allocates 1MB of memory, even if your line is only 12 characters long. The default is 1,024 bytes, which should be enough for almost all appliances.

Try to decide whether you really need to load the entire file into memory when processing a file. Suppose you need to scan a text file for occurrences of a defined phrase with a regular expression. If you load the file into memory with the file_get_contents() function and then run the preg_match_all() function, you actively waste many resources. It would be more efficient to use a while (!feof($fp)) { $line = fgets($fp); } loop, which doesn't waste memory by loading the entire file into memory. It would speed up the regular expression matching as well.

9.2.2. Program Input/Output

Much like UNIX has the paradigm "All IO is a file," PHP has the paradigm "All IO is a stream." Thus, when you want to work with the input and output of a program, you open a stream to that program. Because you need to open two channels to your programone for reading and one for writingyou use one of two special functions to open the streams: popen() or proc_open(). popen()

popen() is the simpler function, providing only unidirectional IO to a program; you can only use w or r as the opening mode. When you open a stream to a program, also called a pipe (hence the name popen()), you can use all the normal file functions to read or write from the pipe, and use (for example) feof() to check if there is no more input to read. Here is a small example that reads the output of ls l /:

 <?php $fp = popen('ls l /', 'r'); while (!feof($fp)) {     echo fgets($fp); } pclose($fp); ?> proc_open()

popen() is seldom useful because you cannot perform any interactive tasks with the opened process. But don't worryPHP has a function to provide the missing functionality: proc_open(). With proc_open(), you can link all the input and output handlers of a process to either a pipe from which you can read or a pipe to which you can write from your script, or a file. A pipe is treated as a file handle, except that you can never open a file handle for reading and writing at the same time.

proc_open() requires three parameters:

 resource proc_open ( string cmd, array descriptorspec, array pipes) 

The cmd parameter is the command to execute, such as /usr/local/bin/php. You don't need to specify the full path to the executable used by popen() if your executable is in the system path.

The descriptorspec parameter is more complex. descriptorspec is an array with each element describing a file handler for input or output. File Descriptors
 <?php     $fin = fopen("readfrom", "r");     $fout = fopen("writeto", "w");     $desc = array (0 => $fin, 1 => $fout);     $res = proc_open("php", $desc, $pipes);     if ($res) {         proc_close($res);     } ?> 

This script starts a PHP interpretera child process. It links the input for the child process to the file descriptor $fin (which is a file handler for the file "readfrom") and the output of the child process to $fout (which is a file handler for the file "writeto"). The "readfrom" file contains

 <?php echo 'Hello you!'; ?> 

After the execution of the script, the file "writeto" contains

 Hello you! P|pes

Instead of using a file handler for input and output to the PHP child process, as shown in the script in the previous section, you can open pipes to the child process that allow you to control the spawned process from your script. The following script sends the <?php echo 'Hello you!'; ?> script from the script itself to the spawned PHP interpreter. The script writes the output of the echo statement to the standard output of the script, applying urlencode to the output text string "Hello you!".

 <?php $descs = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w')); $res = proc_open("php", $descs, $pipes); if (is_resource($res)) {      fputs($pipes[0], '<?php echo "Hello you!\n"; ?>');      fclose($pipes[0]);      while (!feof($pipes[1])) {            $line = fgets($pipes[1]);            echo urlencode($line);      }      proc_close($res); } ?> 

The output is
 Hello+you%21%0A Files

You can pass a file as the handler for the file descriptors to your process, as shown in the following example:

 <?php $descs = array(     0 => array('pipe', 'r'),     1 => array('file', 'output', 'w'),     2 => array('file', 'errors', 'w') ); $res = proc_open("php", $descs, $pipes); if (is_resource($res)) {     fputs($pipes[0], '<?php echo "Hello you!\n"; ?>');     fclose($pipes[0]);     proc_close($res); } ?> 

The output file now contains
 Hello you! 

and the 'errors' file is empty.

In addition to the input pipe[0] and the output pipe[1] shown in the previous examples, you can use other pipes to redirect all file descriptors of the child process. In the preceding example, we redirect all error messages sent to the standard error descriptor (2) to pipe[2], the file errors. The index of the $descs array is not limited to the indices 0-2, so that you can always fiddle with all file descriptors as suits you. However, those additional file descriptors, with an index larger than 2, do not work yet on Windows because PHP doesn't implement a way for the client process to attach to them. Perhaps this will be addressed as PHP develops.

9.2.3. Input/Output Streams

With PHP, you can use stdin, stdout, and stderr as files. These "files," linked with the stdin, stdout, and stderr stream of the PHP process, can be accessed by using a protocol specifier in the call to fopen(). For the program input and output streams, this specifier is php://. This feature is most useful when working with the Command Line Interface (CLI), which is explained in more detail in Chapter 16, "PHP Shell Scripting."

Two more IO streams are available: php://input and php://output. With php://input, you can read raw POST data. You may want to do so when you need to process WebDAV requests or obtain data from the POST requests yourself, which can be useful when working with WebDAV, XML-RPC, or SOAP. The following example shows how to obtain form data from a form that has two fields with the same name:

 form.html: <html>     <form method="POST" action="process.php">         <input type="text" name="example">         <select name="example">             <option value="1">Example line 1</option>             <option value="2">Example line 2</option>         </select>         <input type="submit">     </form> </html> process.php:      <h1>Dumping $_POST</h1>      <?php           var_dump ($_POST);      ?>      <h1>Dumping php://input</h1>      <?php            $in = fopen ("php://input", "rb");            while (!feof($in)) {                  echo fread ($in, 128);            }      ?> 

The first script contains only HTML code for a form. The form has two elements with the name "example": a text field and a select list. When you submit the form by clicking the submit query button, the script process.php runs and displays the output shown in Figure 9.1.

Figure 9.1. php://input representation of POST data

As you can see, only one elementthe selected value from the select listis displayed when you dump the $_POST array. However, the data from both fields shows up in the php://input stream. You can parse this raw data yourself. Although, raw data might not be particularly useful with simple POST data, it's useful to process WebDAV requests or to process requests initiated by other applications.

The php://output stream can be used to write to PHP's output buffers, which is essentially the same as using echo or print(). php://stdin and php://input are read-only; php://stdout, php://stderr, and php://output are write-only.

9.2.4. Compression Streams

PHP provides some wrappers around compression functions. Previously, you needed specialized functions for accessing gzip and bzip compressed files; you can now use the streaming support for those libraries. Reading from and writing to a gzipped or bzipped file works exactly the same as reading and writing a normal file. To use the compression methods, you need to compile PHP with --with-zlib to provide the compress.zlib:// wrapper and --with-bz2 to provide the compress.bzip2:// wrapper. Of course, you need to have the zlib and/or bzip2 libraries installed before you can enable those extensions.

Gzip streams support more mode specifiers then the standard r, w, a, b, and +. These additional modifiers include the compression level 1-9 and the compression methods f for filtered and h for huffman only compressing. These modifiers only make sense if you open the file for writing.

In the following example, we demonstrate copying a file from a bzipped file to a gzipped file. We make use of the compression level specifier 1 to speed up compression, and the third parameter fopen(), to specify searching for the file in the include path. Be careful when using the include path parameter because it will have a performance impact on your script. PHP tries to find and open the file throughout the entire include path, which slows down your script because file operations are generally show operations on most operating systems.

 <?php ini_set ('include_path', '/var/log:/usr/var/log:.'); $url = 'compress.bzip2://logfile.bz2'; $fil = 'compress.zlib://foo1.gz'; $fr = fopen($url, 'rb', true); $fw = fopen($fil, 'wb1'); if (is_resource($fr) && is_resource($fw)) {     while (!feof($fr)) {         $data = fread($fr, 1024);         fwrite($fw, $data);     }     fclose($fr);     fclose($fw); } ?> 

This script first sets the include path to /var/log, /usr/var/log, and the current directory (.). Next, it tries to open the logfile.bz2 file from the include path and opens the foo1.gz file for writing with compression level 1. If both streams are opened successfully, the script reads from the bzipped file until it reaches the end and writes the contents directly into the gzipped file. When the script finishes copying the contents, it closes the streams.


Another great aspect about streams is that you can nest wrappers. For example, you can open them from the following URL: compress.zlib://

9.2.5. User Streams

The streams layer in PHP 5 allows defining User Streamsstream wrappers implemented in PHP code. This User Stream is implemented by a class and, for every file operation (opening, reading, for instance), you need to implement a method. This section describes the methods that must be implemented. boolean stream_open ( string path, string mode, int options, string opened_path);

This function is called when fopen() is called on this stream. The path is the full URL as specified in the fopen() call, which you need to interpret correctly. The parseurl() function helps for this. You also need to validate the mode yourself. The options parameter, set by the stream's API, is a bit field consisting of the following constants:

  • STREAM_USE_PATH. This constant is set in the bit field when trUE was passed as the use_include_path parameter to fopen(). It's up to you to do something with it if needed.

  • STREAM_REPORT_ERRORS. If this constant is set, you need to handle trigger errors yourself with the trigger_error() function; if it's not set, you should not raise any errors yourself. void stream_close ( void );

The stream_close method is called when fclose() is called on the stream, or when PHP closes the stream resource during shutdown. You need to take care of releasing any resources that you might have locked or opened. string stream_read ( int count);

When fgets() or fread() triggers a read request on the stream, the stream_read method is called in response. You should always try to return count bytes from the stream. If there is not much data available, just return as many bytes as you have left in the stream. If no data is available, return FALSE or an empty string. Do not forget to update the read/write position of the stream. This position is usually stored in the position property of your class. int stream_write ( string data);

The stream_write method is called when fputs() or fwrite() is called on this stream. You should store as much of the data as possible, and return the number of bytes that actually were stored in the container. If no data could be stored, you should return 0. You should also take care of updating the position pointer. boolean stream_eof ( void );

This method is called when feof() is called on the stream. Return TRUE if the end of the stream is reached, or FALSE if the end has not been reached yet. int stream_tell ( void );

The stream_tell() method is called on a ftell() request on the stream. You should return the value of the read/write position pointer. boolean stream_seek ( int offset, int whence);

stream_seek is called when fseek() is applied on the stream handle. The offset is an integer value that moves the file pointer (seeking) back (on a negative number) or forward (on a positive number). The seek offset is calculated based on the second parameter, which has one of the following constants:

  • SEEK_SET. The offset passed to the function should be calculated from the beginning.

  • SEEK_CUR. The offset is relative to the current stream position.

  • SEEK_END. The offset is relative to the end of the stream. Positions in the stream have a negative offset; positive offsets correspond with positions after the end of the stream.

The function should implement the changing of the stream pointer and return trUE if the position could be changed, or FALSE if the seek could not be executed. boolean stream_flush ( void );

Your user stream may cache data written to the stream for better performance. The stream_flush() method is called when the user commits all cached data with the fflush() function. If there was no cached data or all cached data could be written to the storage container (such as a file or a table in a database), the function should return trUE; if the cached data could not be committed to the storage container, it should return FALSE.

9.2.6. URL Streams

The last category of streams is URL streams. URL streams have a path that resemble a URL, such as or In fact, all special wrappers use a URL-like path, such as compress.zlib://file.gz. However, only schemes that resemble a remote resource, such as a file on an FTP server or a document on a gopher server, fall into the category URL streams. The basic URL streams that PHP supports are

  • http://. For files located on an HTTP server

  • https://. For files located on an SSL enhanced HTTP server

  • ftp://. For files on an FTP server

  • ftps://. For files on an FTP server with SSL support

SSL support for HTTP and FTP is only available if you added OpenSSL by specifying --with-openssl when you configured PHP. For authentication to HTTP or FTP servers, you can prefix the hostname in the URL with username:password@, as in the following:

 $fp = fopen ('', 'wb'); 

The HTTP handler only supports the reading of files, so you need to specify the mode rb. (Strictly, the b is only needed on Windows, but it doesn't hurt to add it.) The FTP handler supports opening a stream only in either read or write mode, but not in both simultaneously. Also, if you try to open an existing file for writing, the connection fails, unless you set the 'overwrite' context option (see Figure 9.2):

 <?php     $context = stream_context_create (array('ftp' => array('overwrite' => true));     $fp = fopen('', 'wb', false, $context); ?> 

Figure 9.2. phpsuck in action.

The following example demonstrates reading a file from an HTTP server and saving it into a compressed file. This example also introduces a fourth parameter to the fopen() call that specifies a context for the stream. By using the context parameter, you can set special options for a stream. For example, you can set a notifier. This notifier callback will be called on different events during the transaction:

 #!/usr/local/bin/php <?php /* Check for arguments */ if ($argc < 2) {     echo "Usage:\nphpsuck.php url [max kb/sec]\n\n";     exit(-1); } /* Url to fetch */ $url = $argv[1]; /* Bandwidth limiting */ if ($argc == 3) {     $max_kb_sec = $argv[2]; } else {     $max_kb_sec = 1000; } /* Cursor to column 1 for xterms */ $term_sol = "\x1b[1G"; $severity_map = array (     0 => 'info   ',     1 => 'warning',     2 => 'error  ' ); /* Callback function for stream events */ function notifier($code, $severity, $msg, $xcode, $sofar, $max) {     global $term_sol, $severity_map, $max_kb_sec, $size;     /* Do not print status message prefix when the PROGRESS      * event is received. */     if ($code != STREAM_NOTIFY_PROGRESS) {         echo $severity_map[$severity]. ": ";     }     switch ($code) {         case STREAM_NOTIFY_CONNECT:             printf("Connected\n");             /* Set begin time for kb/sec calculation */             $GLOBALS['begin_time'] = time() - 0.001;             break;         case STREAM_NOTIFY_AUTH_REQUIRED:             printf("Authentication required: %s\n", trim($msg));             break;         case STREAM_NOTIFY_AUTH_RESULT:             printf("Logged in: %s\n", trim($msg));             break;         case STREAM_NOTIFY_MIME_TYPE_IS:             printf("Mime type: %s\n", $msg);             break;         case STREAM_NOTIFY_FILE_SIZE_IS:             printf("Downloading %d kb\n", $max / 1024);             /* Set the global size variable */             $size = $max;             break;         case STREAM_NOTIFY_REDIRECTED:             printf("Redirecting to %s...\n", $msg);             break;         case STREAM_NOTIFY_PROGRESS:             /* Calculate the number of stars and stripes */             if ($size) {                 $stars = str_repeat ('*', $c = $sofar * 50 / $size);             } else {                 $stars = '';             }             $stripe = str_repeat ('-', 50 - strlen($stars));             /* Calculate download speed in kb/sec */             $kb_sec = ($sofar / (time() - $GLOBALS['begin_time'])) / 1024;             /* Pause the script if we are above the maximum suck              * speed */             while ($kb_sec > $max_kb_sec) {                 usleep(1);                 $kb_sec = ($sofar / (time() - $GLOBALS['begin_time'])) / 1024;             }             /* Display the progress bar */             printf("{$term_sol}[%s] %d kb %.1f kb/sec",                 $stars.$stripe, $sofar / 1024, $kb_sec);             break;         case STREAM_NOTIFY_FAILURE:             printf("Failure: %s\n", $msg);             break;     } } /* Determine filename to save too */ $url_data = parse_url($argv[1]); $file = basename($url_data['path']); if (empty($file)) {     $file = "index.html"; } printf ("Saving to $file.gz\n"); $fil = "compress.zlib://$file.gz"; /* Create context and set the notifier callback */ $context = stream_context_create(); stream_context_set_params($context, array ("notification" =>  "notifier")); /* Open the target URL */ $fp = fopen($url, "rb", false, $context); if (is_resource($fp)) {     /* Open the local file */     $fs = fopen($fil, "wb9", false, $context);     if (is_resource($fs)) {         /* Read data from URL in blocks of 1024 bytes */         while (!feof($fp)) {             $data = fgets($fp, 1024);             fwrite($fs, $data);         }         /* Close local file */         fclose($fs);     }     /* Close remote file */     fclose($fp);     /* Display download information */     printf("{$term_sol}[%s] Download time: %ds\n",         str_repeat('*', 50), time() - $GLOBALS['begin_time']); } ?> 

Some events can be handled in the notify callback function. Although most are only useful for debug purposes (NOTIFY_CONNECT, NOTIFY_AUTH_REQUIRED, NOTIFY_AUTH_REQUEST), others can be used to perform some neat tricks, like the bandwidth limiting we do in the previous example. The following is a full list of all the different events.


This event is fired when a connection with the resource has been established for example, when the script connected to a HTTP server.


When a request for authorization is complete, this event is triggered by the stream's API.


As soon as the authentication has finished, this event is triggered to tell you if there was a successful authentication or a failure.


The HTTP stream wrapper (http:// and https://) fires this event when the Content-Type header is available in the response to the HTTP request.


This event is triggered when the FTP wrapper figures out the size of the file, or when an HTTP wrapper sees the Content-Length header.


This event is triggered by the HTTP wrapper when it encounters a redirect request (Location: header).


This is one of the fancier events; it is used extensively in our example. It's sent as soon as a packet of data has arrived. In our example, we used this event to perform bandwidth limiting and display the progress bar.


When a failure occurs, such as the login credentials were wrong, the wrapper triggers this event.

9.2.7. Locking

While writing to files that are possibly being read by other scripts at the same time, you will run into problems at some point because a write might not totally be completed while another script is reading the same file. The reading script will only see a partial file at that moment. Preventing this problem is not hard to do, and the method for this is called locking.

PHP can set locks on files with the flock() function. Locking a file prevents a reading script from reading a file when it is being written to by another script; the only prerequisites for this is that both scripts (the reader and the writer) implement the locking. A simple set of scripts may look like this:

 <?php /* writer */     while (true) {         $fp = fopen('testfile', 'w');         echo "Waiting for lock...";         flock($fp, LOCK_EX);         echo "OK\n"; 

flock($filepointer, LOCK_EX); tries to acquire an exclusive lock on the file and blocks until this lock can be acquired. An exclusive lock will only be granted if there are no other locks on the file.

 $date =  date("Y-m-d H:i:s\n"); echo $date; fputs($fp, $date); sleep(1); echo "Releasing lock..."; flock($fp, LOCK_UN); echo "OK\n"; 

After we write to the file, we can release the lock with flock($fp, LOCK_UN);:

 fclose($fp);         usleep(1);     } ?> <?php /* reader */     while (true) {         $fp = fopen('testfile', 'r');         echo "Waiting for lock...";         flock($fp, LOCK_SH);         echo "OK\n"; 

Here, we request a shared lock. This lock will not be granted if there is an exclusive lock set on this file, but it will be granted if there is another shared lock, or no lock at all on this file. This means that it is possible to have multiple readers reading from the file at the same time, unless a writer process locks the file with its exclusive lock.

         echo fgets($fp, 2048);         echo "Releasing lock...";         flock($fp, LOCK_UN);         echo "OK\n";         fclose($fp);         sleep(1);     } ?> 

At the end of the script, we sleep for 1 second so that we are not using 100 percent CPU time.

9.2.8. Renaming and Removing Files

PHP provides the unlink() function for deleting a file, which "unlinks" the file from a directory. On a UNIX-like system the file will only be deleted if no programs have this file in use. This means that with the following script, the bytes associated with the file will only be released to the operating system after the fclose() is executed:

 <?php     $f = fopen("testfile", "w");     unlink("testfile");     sleep(60);     fclose($f); ?> 

During execution, you will not see the file in the directory anymore after unlink() is run. But, lsof still shows the file as being in use, and you can still read from it and write to it:

 $ sudo lsof | grep testfile php  14795  derick  3w  REG  3,10  0  39636 /unlink/testfile (deleted) 

Moving a file in PHP with the rename() function is atomic if you move/rename the file to a place which is on the same file system. Atomic means that nothing can interfere with this, and that it is always guaranteed not to be interrupted. In case you want to move a file to a different file system, it is safer to do it in two steps, like this:

 <?php       rename('/partition1/file.txt', '/partition2/.file.txt.tmp');       rename('/partition2/.file.txt.tmp', '/partition2/file.txt'); ?> 

The renaming is still not atomic, but the file in the new location will never be there partially, because the renaming from .file.txt.tmp to file.txt is atomic as the rename is on the same file system.

9.2.9. Temporary Files

In case you want to create a temporary file, the best way to do it is with the tmpfile() function. This function creates a temporary file with a unique random name in the current directory and opens this file for writing. This temporary file will be closed automatically when you close the file with fclose() or when the script ends:

 <?php       $fp = tmpfile();       fwrite($fp, 'temporary data');       fclose(fp); ?> 

In case you want to have more control over where the temporary file is created and about its name, you can use the tempnam() function. On the contrary to the tmpfile() function, this file will not be removed automatically:

 <?php       $filename = tempnam('/tmp', 'p5pp');       $fp = fopen($filename, 'w');       fwrite($fp, 'temporary data');       fclose(fp);       unlink($filename); ?> 

The first parameter to the function specifies the directory where the temporary file is created, and the second parameter is the prefix that will be added to the random file name.

    PHP 5 Power Programming
    PHP 5 Power Programming
    ISBN: 013147149X
    EAN: 2147483647
    Year: 2003
    Pages: 240

    Similar book on Amazon © 2008-2017.
    If you may any questions please contact us: