Functions to Chop up Files in PHP
PHP Help from NicholasSolutions
Contents
0. Introduction
Sometimes it's useful to be able to chop up a file into chunks of a certain size. For example, maybe you need to put a large file in a MySQL database, and the file size exceeds the maximum MySQL packet size allowed by your hosting company. Another use might be to allow users to download a large file in parts, and then join them together on their computer with a file joiner. Below are two scripts to help with the task of splitting up files.
First, file_chop() will chop the file up for you and return an array with the pieces. If your file is not
too large, it works very nicely and gives you all the chunks as an array of strings. You can write these to a database or
files, or whatever else you'd like to do. The second function, file_chop_big()
is meant to be used on bigger files. This function does not read the whole file in at once in order to avoid exceeding
PHP's memory limit (the default is 8MB). Instead,
it works one chunk at a time, writing the files to disk, and returns an array of the chunks' file names. You can use this
function on smaller files, too, if you'd rather write the chunks to disk than hold them in memory. To use
file_chop_big(), the user running PHP (usually your web server) will need write access to the folder where you put the script.
1. The functions
data array file_chop(string file_path, int chunk_size)
function file_chop($file_path, $chunk_size){
$handle = fopen($file_path, 'rb'); //read the file in binary mode
$size = filesize($file_path);
$contents = fread($handle, $size);
fclose($handle);
//find number of full $chunk_size byte portions
$num_chunks = floor($size/$chunk_size);
$chunks = array();
$start = 0;
for ($kk=0; $kk < $num_chunks; $kk++){
$chunks[] = substr($contents, $start, $chunk_size); //get $chunk_size bytes at a time
$start += $chunk_size;
}
if ($start < $size){
$chunks[] = substr($contents, $start); //get any leftover
}
return $chunks;
}
filename array file_chop_big(string file_path, int chunk_size)
function file_chop_big($file_path, $chunk_size){
$size = filesize($file_path);
//find number of full $chunk_size byte portions
$num_chunks = floor($size/$chunk_size);
$file_handle = fopen($file_path, 'rb'); //read the file in binary mode
$chunks = array();
for ($kk=0; $kk < $num_chunks; $kk++){
$chunks[$kk] = basename($file_path).'.chunk'.($kk+1);
$chunk_handle = fopen($chunks[$kk], 'w'); //open the chunk file for writing
//write the data to the chunk file 1k at a time
while((ftell($chunk_handle) + 1024) <= $chunk_size){
fwrite($chunk_handle, fread($file_handle, 1024));
}
if(($leftover = $chunk_size-ftell($chunk_handle)) > 0 ){
fwrite($chunk_handle, fread($file_handle, $leftover));
}
fclose($chunk_handle);
}
if (($leftover = $size - ftell($file_handle)) > 0){
$chunks[$num_chunks] = basename($file_path).'.chunk'.($num_chunks + 1);
$chunk_handle = fopen($chunks[$num_chunks], 'w');
while(!feof($file_handle)){
fwrite($chunk_handle, fread($file_handle, 1024));
}
fclose($chunk_handle);
}
fclose($file_handle);
return $chunks;
}
2. Examples
Using these functions should be pretty self-explanatory. Both accept a string containing the path of the file to split,
and an integer equal to the size of the desired chunks in bytes (1 kb = 1024 bytes, 1 MB = 1048576 bytes). Both functions return
arrays. The difference is that file_chop() returns an array of the data chunks themselves, whereas file_chop_big()
writes the chunks to disk (each saved as filename.chunk1, filename.chunk2, filename.chunk3, etc.), and returns an array
of strings containing the file names of the chunks. In both cases, the last chunk will usually be smaller than the others (which are
equal in size to the chunk size argument).
Here's an example of using file_chop() to save a file in a database:
<?php
$path = 'file.mp3'; //the file to chop up
$bytes = 512000; //size of the chunks in bytes (500k in this case)
$pieces = file_chop($path, $bytes);
echo "$path was chopped into " . count($pieces) . " $bytes-byte chunks stored in $pieces";
//the last piece may be smaller than $bytes bytes
foreach ($pieces as $bit){
//insert $bit into your database
}
?>

