Oliver
Oliver

Reputation: 1

Split file into multiple byte ranges

I want to split a file into multiple byte ranges, less than 4 MB, because the Mail Server doesn't allow Mails bigger than 4MB. I'm trying to find a solution in in PHP. I set up a upload session (https://learn.microsoft.com/en-us/graph/outlook-large-attachments?tabs=http#step-1-create-an-upload-session) but for that to work i need to split the Mails that are larger than 4MB into chunks. Any suggestions ?

Upvotes: 0

Views: 580

Answers (1)

ChrisCarcaud
ChrisCarcaud

Reputation: 46

for years, a backup application has been working like this: collect the files in zip, split them into 2 Mb files, upload them to the server and then rebuild the origin ZIP files.

The chunk/glue file class class FileSplitter {

/**
 * Chunk input file to smaller files
 * @param type $input_filename
 * @param type $chunksize
 * @param type $destpath
 * @return string
 * @throws Exception
 */
static public function writeChunks($input_filename, $chunksize, $destpath = '') {
    $out_files = array();

    //Input file exists
    if (!file_exists($input_filename) || !is_readable($input_filename)) {
        throw new Exception('File not exists ' . $input_filename);
    }

    //Destination chunks
    $chunk_number = 1;
    $info = pathinfo($input_filename);
    if (!empty($destpath)) {
        $output_dir = rtrim($destpath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
    } else {
        $output_dir = '';
    }
    $output_filename = $output_dir . $info['filename'] . '.' . str_pad($chunk_number, 3, '0', STR_PAD_LEFT);

    $rh = fopen($input_filename, 'rb');
    $wh = fopen($output_filename, 'wb');
    $out_files[] = $output_filename;

    if ($rh!=false && $wh!=false) {
        while (!feof($rh)) {
            $buf = fread($rh, 1024);
            fwrite($wh, $buf);

            if (ftell($wh) >= $chunksize) {
                fclose($wh);

                $chunk_number++;
                $output_filename = $output_dir . $info['filename'] . '.' . str_pad($chunk_number, 3, '0', STR_PAD_LEFT);
                $out_files[] = $output_filename;
                $wh = fopen($output_filename, 'wb');
                if ($wh==false) {
                   fclose($rh);
                   throw new Exception('output file open error '); 
                }
            }
        }

        fclose($wh);
        fclose($rh);
    } else {
       throw new Exception('Input or output file open error '); 
    }

    return $out_files;
}

static public function glueChunks($chunk_list, $output_filename) {
    $wh = fopen($output_filename, 'wb');

    foreach ($chunk_list as $chunk_file) {
        $rh = fopen($chunk_file, 'rb');
        if ($rh) {
            while (!feof($rh)) {
                $buf = fread($rh, 1024);
                fwrite($wh, $buf);
            }
            fclose($rh);
        }
    }
    fclose($wh);
}

}

How to use

$CHUNK_SIZE = 1024 * 1024 * 2;
//split into chunks
$n_chunks = FileSplitter::writeChunks(realpath($n_Backup['archive']), $CHUNK_SIZE, sys_get_temp_dir());

//Assemble to one file
$n_chunks = FileSplitter::writeChunks($n_chunks,'big_file.zip');

Maybe you can adapt source code to Mail Server

Upvotes: 1

Related Questions