PHP File System Management

File System Management

In this lesson of the PHP tutorial, you will learn… 

  1. To read from files on the server.
  2. To write to files on the server.
  3. To upload files to the server.
  4. To get information about files on the server.
  5. To access and work with directories on the server.

Most Web applications use databases to store large amounts of data. However, in some cases, it will be necessary to store data in or access data from files.

Opening a File

fopen()

Syntax
fopen (path_to_file, file_mode)

path_to_file can either be a relative or an absolute path.

File Modes
File Mode Description
r open for reading
w open for writing (erases existing content); creates new file if one doesn’t exist
a open for appending to end of content; creates new file if one doesn’t exist
x create and open for writing (new in PHP 4.3.2); fails and returns false if file already exists
r+ open for reading and writing (erases existing content when file is written to)
w+ open for writing and reading (erases existing content on opening or creates new file if one doesn’t exist
a+ open for appending and writing; creates new file if one doesn’t exist
x+ create and open for writing and reading (new in PHP 4.3.2); fails and returns false if file already exists

File Permissions

Files that do no have the appropriate permissions settings will fail to open. In this case, the fopen() function will return false and a warning will be given. Use conditional processing as shown below to handle this situation.

$MyFile = @fopen('MyFile.txt','a');
if (!$MyFile)
{
 echo '<b>Sorry, but the file cannot be opened.</b>';
}
else
{
 // code for processing file
}

The @ symbol in front of first line of code is used to suppress errors. Any errors can then be handled more gracefully.

Reading from a File

Opening a file for reading involves three steps:

  1. Open the file.
  2. Read the file.
  3. Close the file.

fgets()

fgets() is used to read a file one line at a time. It requires one argument: the resource or “handle” for the file and accepts a second argument: the length of the line. It will continue reading the line until the length – 1 have been read or it reaches the end of the line or the end of the file. If the second argument is not included, it will continue reading until it reaches the end of the line.

Examine the file shown below.

Code Sample: Files/Demos/Employees.txt

Nancy Davolio Sales Representative ndavolio@northwind.com
Andrew Fuller Vice President, Sales afuller@northwind.com
Janet Leverling Sales Representative jleverling@northwind.com
Margaret Peacock Sales Representative mpeacock@northwind.com
Steven Buchanan Sales Manager sbuchanan@northwind.com
Michael Suyama Sales Representative msuyama@northwind.com
Robert King Sales Representative rking@northwind.com
Laura Callahan Inside Sales Coordinator lcallahan@northwind.com
Anne Dodsworth Sales Representative adodsworth@northwind.com
Code Explanation

Employees.txt is a tab-delimited text file. Each line is formatted as follows:

FirstName\tLastName\tTitle\tEmail\n

The file is divided into “columns” using tabs (\t) and each “row” is separated by a newline character (\n). The code below opens Employees.txt, reads and displays each line, and closes the file.

Code Sample: Files/Demos/Employees.php

<html>
<head>
  <title>Employees</title>
</head>
<body>
<h1>Employees</h1>
<?php
 $MyFile = @fopen("Employees.txt", 'r');

 if (!$MyFile)
 {
  echo '<p>Cannot open file.';
 }
 else
 {
  while (!feof($MyFile))
  {
   $Employee = fgets($MyFile, 999);
   echo $Employee.'<br />';
  }
  fclose($MyFile);
 }
?>
</body>
</html>
Other options for reading from files
Function Description
fgetss() Like fgets() but it strips out HTML and PHP tags.
fgetcsv() Like fgets() but it splits the file on a specified delimiter rather than a newline character.
readfile() Opens a file, sends its contents to the browser, and closes the file.
file() Opens a file, splits it into an array on newline characters, and closes the file.

Writing to a File

Opening a file for writing involves three steps:

  1. Open the file.
  2. Write to the file.
  3. Close the file.

fwrite()

Syntax
fwrite(file_pointer,output_string)

The output_string is the text to write to the file. See the following example of writing to a file.

$OutputString='text to write';
$MyFile = @fopen('Employees.txt', 'a');
fwrite($MyFile, $OutputString);
fclose($MyFile);

Exercise: Writing to a File

Duration: 10 to 15 minutes.

In this exercise you will write code to append entries to the Employees.txt.

  1. Open Files/Exercises/AddEmployee.php in your editor.
  2. Create short versions of the form variables.
  3. Write code to save the entry in Employees.txt, which is in the same directory. The steps involved are:
    1. Open Employees.txt for appending. Be sure to suppress errors.
    2. Write a condition that checks to see if the file failed to open.
    3. If it did open, write the output string to the file and close the file.

File Locking

flock() (see footnote)

flock() is used to lock a file so that two or more people do not get access to it at the same time. This helps protect the file from being corrupted. flock() takes two arguments: a file handler and a lock type.

Lock Type Explanation
LOCK_SH Reading lock. Others can read file.
LOCK_EX Exclusive lock. The file cannot be opened by others.
LOCK_UN Unlocks file.
LOCK_NB If a file is already locked by another user, flock() waits to get a lock. LOCK_NB tells it not to wait.

The code below shows how we should change Files/Solutions/AddEntry.php to protect Employees.txt from being corrupted.

Code Sample: Files/Demos/Locking.php

---- Code Omitted ----
flock($MyFile, LOCK_EX); fwrite($MyFile,$OutputString); flock($MyFile, LOCK_UN); fclose($MyFile);
---- Code Omitted ----

Uploading Files via an HTML Form (see footnote)

In order to upload files via an HTML form, the form tag’s method must be set to “post” and the enctype must be set to “multipart/form-data” as shown below.

Syntax
<form method="post" enctype="multipart/form-data">

The following example demonstrates how to safely allow the user to upload a file to the server.

Code Sample: Files/Demos/FileUpload.php

<html>
<head>
<title>Resume Upload</title>
</head>
<body style="text-align:center">
<?php
 if (!array_key_exists('Submitted',$_POST)) {
?>
<h2>Resume Upload Form</h2>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="Submitted" value="true">
<table border="1">
<tr>
 <td>First Name</td>
 <td><input type="text" name="FirstName" size="20"></td>
</tr>
<tr>
 <td>Last Name</td>
 <td><input type="text" name="LastName" size="20"></td>
</tr>
<tr>
 <td>Resume</td>
 <td><input type="file" name="Resume"></td>
</tr>
<tr>
 <td colspan="2" align="center"><input type="submit" value="Upload"></td>
</tr>
</table>
</form>
<?php
} else {
 //process the  form
 $ResumeFile = $_FILES['Resume']['tmp_name'];
 $FileSize = $_FILES['Resume']['size'];
 $FileType = $_FILES['Resume']['type'];
 $FileError = $_FILES['Resume']['error'];

 $ResumeName=$_POST['FirstName'] . '_' .
   $_POST['LastName'] . '_Resume.txt';
 if ($FileError)
 {
  echo "We could not upload the file:<br/>$FileError";
  EndPage();
 }
 elseif ($FileType != 'text/plain')
 {
  echo "You have attempted to upload a file of type: $FileType.
    <br/>Only text files allowed.";
  EndPage();
 }

 $FileSavePath = 'Resumes/' . $ResumeName;
 if (is_uploaded_file($ResumeFile))
 {
  if (!move_uploaded_file($ResumeFile,$FileSavePath))
  {
   echo 'Could not save file.';
   EndPage();
  }
 }
 else
 {
  //This case happens if somehow the file
  //we are working with was already on the server.
  //It's to stop hackers.
  echo 'Hey, what is going on here?
     Are you being bad?';
  EndPage();
 }
 $Resume=makeFileSafe($FileSavePath);
?>
 <h2>Thanks!</h2>
 <b>We got your resume.</b><hr>
 <form>
 <textarea cols="60" rows="20"><?echo $Resume?></textarea>
 </form>
 </p>
<?php
}

function EndPage()
{
 echo '</body></html>';
 exit;
}

function makeFileSafe($FilePath)
{
 $FP = @fopen($FilePath,'r+');
 if (!$FP)
 {
  return "Could not read file";
 }
 $Contents = fread($FP,filesize($FilePath));
 $Contents = strip_tags($Contents);
 rewind($FP);
 fwrite($FP,$Contents);
 fclose($FP);
 return $Contents;
}
?>
</body>
</html>
Code Explanation

The first thing to notice about this page is that it submits to itself. The first time it is loaded, it will show the form. When the form is submitted, it will attempt to upload and save the user’s resume.

  1. The form also has an input field of type file that is used to browse for the file to upload.
  2. When the form is submitted, the script assigns values to short named variables.
  3. The next block of code is the if-elseif-elseif statement, which checks for errors. If it finds any, it displays an appropriate message and calls the EndPage() user function, which just closes the HTML page.
  4. The next piece of code attempts to upload the file:
    if (is_uploaded_file($ResumeFile))
    {
     if (!move_uploaded_file($ResumeFile,$FileSavePath))
     {
      echo 'Could not save file.';
      EndPage();
     }
    }
    else
    {
     //This case happens if somehow the file
     //we are working with was already on the server.
     //It's to stop hackers.
     echo 'Hey, what is going on here?
        Are you being bad?';
     EndPage();
    }
  5. The last bit of PHP code on the page calls the makeFileSafe() user function which opens the resume file, strips out all the tags from its contents and closes it.

Getting File Information

The following code sample illustrates how to get information about a file using PHP.

Code Sample: Files/Demos/FileInfo.php

<html>
<head>
  <title>File Details</title>
</head>
<body>
<?php
 $CurrentDir = 'Resumes/';
 $File = basename('J_C_Resume.txt');
 echo '<h1>Details of file: ' . $File.'</h1>';
 $File = $CurrentDir.$File;

 echo '<h2>File data</h2>';
 echo 'File last accessed: ' .
   date('j F Y H:i', fileatime($File)) . '<br/>';
 echo 'File last modified: ' .
   date('j F Y H:i', filemtime($File)).'<br/>';
 echo 'File type: ' . filetype($File).'<br/>';
 echo 'File size: '.filesize($File).' bytes<br/>';

 echo '<h2>File tests</h2>';
 echo 'is_dir: ' .
  (is_dir($File)? 'true' : 'false') . '<br/>';
 echo 'is_file: ' .
  (is_file($File)? 'true' : 'false').'<br/>';
 echo 'is_readable: ' .
  (is_readable($File)? 'true' : 'false').'<br/>';
 echo 'is_writable: ' .
  (is_writable($File)? 'true' : 'false').'<br/>';
?>
</body>
</html>
Code Explanation

The functions used in this script are described in the following table.

Function Description
basename() Strips off the path and returns the file name.
fileatime() Returns the last accessed time of the file.
filemtime() Returns the last modified time of the file.
filetype() Returns the type of file (e.g, file or dir).
filesize() Returns the size of the file in bytes.
is_dir() Returns true if the passed value is a directory, false if it isn’t.
is_file() Returns true if the passed value is a file, false if it isn’t.
is_readable() Returns true if the file is readable, false if it isn’t.
is_writable() Returns true if the file is writable, false if it isn’t.

More File Functions

A few more file functions are shown below:

Function Description
file_exists(path_to_file) Checks to see if a file exists.
filesize(path_to_file) Returns the size of file in bytes.
unlink(path_to_file) Deletes the file.
copy() Copies a file. Takes two arguments: the path to the source file and the destination to copy the source file to.
rename() Moves a file. Takes two arguments: the path to the source file and the destination to move the source file to. If the path and destination are the same with the exception of the filename, rename() simply renames the file.

Directory Functions

The following table shows some of the more common directory functions.

Function Description
mkdir() Creates a directory.
rmdir() Deletes a directory.
opendir() Opens a directory for reading.
readdir() Reads the contents of an open directory.

Getting a Directory Listing

To get a directory listing, use the opendir() function to open the directory and the readdir() function to read its contents. Then loop through its contents with a while loop outputting the name of each file and folder.

Exercise: Creating a Resume Management Page

Duration: 20 to 30 minutes.

In this exercise, you will create a simple resume management page that will list all the resumes currently in the resumes folder and allow you to remove resumes from the folder.

  1. Open Files/Exercises/FileListing.php in your editor. Much of the file is done already.
  2. Complete the fileDetails() function so that it will properly display the details of the passed file.
  3. At the end of the if block of the fileDetails() function there is a “Delete File” link. Modify this link so that it passes the file path in the “Delete” variable via the query string.
  4. Write the browseDir() function.
  5. Write the deleteFile() function.

Write a renameFile() function and add a form to the fileDetails() function that allows the user to provide a new name for the file.

File System Management Conclusion

Although writing to and reading from files can be useful in certain situations, when it is important to be able to access and change data quickly and to maintain the integrity of that data, it is often better to use a database.

Many websites allow visitors to upload files via a form. In this lesson, we have stored those files in a directory under the web root. For security reasons, this is generally not a good idea. In practice, you should store any uploaded files above or outside of the web root.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s