使用PHP拆分大文件

13

我想从php代码中将大文件(具体来说是tar.gz文件)拆分成多个部分。主要原因是,32位系统上php的2GB限制。

因此,我想将大文件拆分成多个部分并逐个处理每个部分。

这是否可行?如果可以,如何操作?


1
这不是PHP的任务。你在用什么操作系统? - Pekka
4
可以使用 exec() 函数来执行命令 split -b 2048 m file.tar.gz pieces 进行文件的分割操作。 - alex
@alex 非常有趣.... - James Walker
9个回答

12

我的评论被投票赞成两次,所以也许我的猜测有点准 :P

如果在Unix环境下,请尝试以下操作...

exec('split -d -b 2048m file.tar.gz pieces');

split

你的分片应该是 pieces1pieces2 等等。

你可以通过在 PHP 中使用 stat() 获取文件大小并进行简单数学计算得到分片数,即 (int) ($stat['size'] / 2048*1024*1024)(我想是这个)。


非常有趣...绝对值得深入研究...为这个概念点赞。 - James Walker

10

如果使用基于Linux的服务器,一种简单的方法是使用exec命令并运行split命令:

exec('split Large.tar.gz -b 4096k SmallParts'); // 4MB parts
/*    |     |            |      | |
      |     |            |______| |
      App   |                 |   |_____________
            The source file   |                 |
                              The split size    Out Filename
*/

更多详细信息请参见:http://www.computerhope.com/unix/usplit.htm

或者你可以使用:http://www.computerhope.com/unix/ucsplit.htm

exec('csplit -k -s -f part_ -n 3 LargeFile.tar.gz');

PHP只能在单个线程中运行,增加线程数的唯一方法是使用fork命令创建子进程。

这种方法并不友好于资源。我建议考虑使用一种可以快速有效地完成此任务的语言,比如node.js。

只需在服务器上安装node,然后创建一个小脚本,例如叫做node_split,它可以自行完成该任务。

但我强烈建议不要使用PHP来完成此任务,而是使用exec来让主机操作系统处理它。


exec 可能在许多共享主机上被禁用,因此对我无效。 - Mihir
我原本的假设是,如果他使用共享主机,他的服务器上不会有这么大的文件。 - RobertPitt

3

我认为这不会起作用,因为32位系统上的PHP甚至无法打开大于2GB的文件。 - Mihir

1
$handle = fopen('source/file/path','r'); 
        $f = 1; //new file number
        while(!feof($handle))
        {
            $newfile = fopen('newfile/path/'.$f.'.txt','w'); //create new file to write to with file number
            for($i = 1; $i <= 5000; $i++) //for 5000 lines
            {
                $import = fgets($handle);
                //print_r($import);
                fwrite($newfile,$import);
                if(feof($handle))
                {break;} //If file ends, break loop
            }
            fclose($newfile);
            $f++; //Increment newfile number
        }
        fclose($handle);

1

PHP本身可能无法... 如果您能够从计算机的命令行中找出如何执行此操作, 然后您应该能够使用exec();执行这些命令。


exec 可能在许多共享主机上被禁用,因此对我无效。 - Mihir

1
function split_file($source, $targetpath='/split/', $lines=1000){

    $i=0;
    $j=1;
    $date = date("m-d-y");
    $buffer='';

    $handle = fopen ($_SERVER['DOCUMENT_ROOT'].$source, "r");

    while (!feof ($handle)) {
        $buffer .= fgets($handle, 4096);
        $i++;
        if ($i >= $lines) {
            $fname = $_SERVER['DOCUMENT_ROOT'].$targetpath."part_".$date.$j.".txt";

                 $fhandle = fopen($fname, "w") or die($php_errormsg);

            if (!$fhandle) {
                echo "Cannot open file ($fname)";
                //exit;
            }


            if (!fwrite($fhandle, $buffer)) {
                echo "Cannot write to file ($fname)";
                //exit;
            }
            fclose($fhandle);
            $j++;
            $buffer='';
            $i=0;
            $line+=10; // add 10 to $lines after each iteration. Modify this line as required
        }
    }
    fclose ($handle);
}

0

分割文件被命名为 filename.part0 filename.part1 ...

<?php
function fsplit($file,$buffer=1024){
    //open file to read
    $file_handle = fopen($file,'r');
    //get file size
    $file_size = filesize($file);
    //no of parts to split
    $parts = $file_size / $buffer;

    //store all the file names
    $file_parts = array();

    //path to write the final files
    $store_path = "splits/";

    //name of input file
    $file_name = basename($file);

    for($i=0;$i<$parts;$i++){
        //read buffer sized amount from file
        $file_part = fread($file_handle, $buffer);
        //the filename of the part
        $file_part_path = $store_path.$file_name.".part$i";
        //open the new file [create it] to write
        $file_new = fopen($file_part_path,'w+');
        //write the part of file
        fwrite($file_new, $file_part);
        //add the name of the file to part list [optional]
        array_push($file_parts, $file_part_path);
        //close the part file handle
        fclose($file_new);
    }    
    //close the main file handle

    fclose($file_handle);
    return $file_parts;
}
?>

0
  • 如果您想拆分已经存在于服务器上的文件,您可以这样做(只需使用文件函数fread、fopen、fwrite、fseek来读取/写入文件的一部分即可)。
  • 如果您想拆分从客户端上传的文件,恐怕您无法这样做。

0

这在php中可能是可行的,但php是为Web开发而构建的,尝试在一个请求中完成整个操作将导致请求超时。

但是,您可以使用另一种语言,如Java或C#,并构建一个后台进程,您可以从php通知执行操作。或者根据主机上的安全设置,甚至可以从php运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接