【问题标题】:Split file into multiple byte ranges将文件拆分为多个字节范围
【发布时间】:2020-08-19 12:48:40
【问题描述】:

我想将一个文件分成多个字节范围,小于 4 MB,因为邮件服务器不允许大于 4 MB 的邮件。我正在尝试在 PHP 中找到解决方案。 我设置了一个上传会话(https://docs.microsoft.com/en-us/graph/outlook-large-attachments?tabs=http#step-1-create-an-upload-session),但为了让它工作,我需要将大于 4MB 的邮件拆分成块。有什么建议吗?

【问题讨论】:

  • 我没有适合您的解决方案,但是许多/大多数邮件服务器会限制整个邮件大小,而不仅仅是附件大小,而且许多/大多数邮件服务器会计算 base64 编码的附件,而不是原始文件。一个 2.92 MB 的文件,在 base64 编码时,会在 base64 编码时膨胀到大约 4 MB,所以这可能是你的最小目标块。消息本身也可能有一些开销,因此可以将其降低到 2.5 MB 以获得不错的安全余量。
  • 是的,正如您所说,整个邮件的大小不允许超过 4MB。我知道 base64,但是为了确定,我可能会将其保持在 2.5 MB 块。
  • 我假设另一端的人也能够重建文件?如果是这样,我会在这里使用其中一种方法:stackoverflow.com/q/5391304/231316
  • 是的。好的,我去看看,谢谢你的帮助!
  • 以上链接需要更好的答案,拆分有点薄split --bytes 4M --numeric-suffixes --suffix-length=3 ./infile.ext ./infile.ext. 然后重新组合cat ./infile.ext.* > ./infile.ext

标签: php


【解决方案1】:

多年来,备份应用程序一直是这样工作的:以 zip 格式收集文件,将它们拆分为 2 Mb 文件,将它们上传到服务器,然后重建原始 ZIP 文件。

块/胶水文件类 类 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);
}

}

如何使用

$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');

也许您可以将源代码改编为邮件服务器

【讨论】:

  • 谢谢!我会努力实现它
猜你喜欢
  • 2016-06-06
  • 2020-02-28
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多