Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何在zip流下载中传输zip?_Php_Stream_Ziparchive_Zipstream - Fatal编程技术网

Php 如何在zip流下载中传输zip?

Php 如何在zip流下载中传输zip?,php,stream,ziparchive,zipstream,Php,Stream,Ziparchive,Zipstream,我希望能够存档(zip,无需压缩,但这是一个优点), 在内存和流中,问题是我想在 我正在播放的zip,如下所示: 档案: a.txt, b.txt, c.txt 流式下载应该如下所示: my.zip { a.txt inner.zip { b.txt, c.txt } } 注意,我必须对文件进行流式处理,因为我没有可用的高清存储,而且我也不能将所有文件都存储在内存中(这就是我对它们进行流式处理的原因) 下面是我设法使用的一个普通的压缩流(没有内部压缩流): 您可以运行一个

我希望能够存档(zip,无需压缩,但这是一个优点),
在内存和流中,问题是我想在
我正在播放的zip,如下所示:

档案:

a.txt, b.txt, c.txt
流式下载应该如下所示:

my.zip {
  a.txt
  inner.zip {
   b.txt, c.txt
  }
}
注意,我必须对文件进行流式处理,因为我没有可用的高清存储
,而且我也不能将所有文件都存储在内存中(这就是我对它们进行流式处理的原因)


下面是我设法使用的一个普通的压缩流(没有内部压缩流):


您可以运行一个小示例,看看使用
ZipArchive
是否能在这方面有所帮助。 在示例的根目录中创建3个名为
a、b、c
的空
.txt
文件

PHP

function RandomString($file)
{
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ';
    $randstring = file_get_contents($file);
    for ($i = 0; $i < 2000000; $i++) {
        $randstring .= $characters[rand(0, strlen($characters))];
    }
    file_put_contents($file,$randstring);
    return true;
}
// fill the 3 files with data up to 2Mb per run
RandomString("a.txt");
RandomString("b.txt");
RandomString("c.txt");

 $zip = new ZipArchive;
    $res = $zip->open('inner.zip', ZipArchive::CREATE);
    if ($res === TRUE) {
    $zip->addFile('b.txt', 'b.txt');
    $zip->addFile('c.txt', 'c.txt');
    $zip->close();
        $resMy = $zip->open('my.zip', ZipArchive::CREATE);

        if ($resMy === TRUE) {
            $zip->addFile('a.txt', 'a.txt');
            $zip->addFile('inner.zip', $contents);
            $zip->close(); 
            unlink('inner.zip');            
            $file_name = basename("my.zip");
            header("Content-Type: application/zip");
            header("Content-Disposition: attachment; filename=$file_name");
            header("Content-Length: " . filesize("my.zip"));
            readfile("my.zip");
            unlink("my.zip");
            exit;
        } else {
            echo 'failed to create my.zip';
        }
    } else {
        echo 'failed to create inner.zip';
    }
函数随机字符串($file)
{
$characters='0123456789abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz';
$randstring=file\u get\u contents($file);
对于($i=0;$i<2000000;$i++){
$randstring.=$characters[rand(0,strlen($characters))];
}
文件内容($file$randstring);
返回true;
}
//每次运行时,用高达2Mb的数据填充3个文件
随机字符串(“a.txt”);
随机字符串(“b.txt”);
随机字符串(“c.txt”);
$zip=新的ZipArchive;
$res=$zip->open('inner.zip',ZipArchive::CREATE);
如果($res==TRUE){
$zip->addFile('b.txt','b.txt');
$zip->addFile('c.txt','c.txt');
$zip->close();
$resMy=$zip->open('my.zip',ZipArchive::CREATE);
如果($resMy==TRUE){
$zip->addFile('a.txt','a.txt');
$zip->addFile('inner.zip',$contents);
$zip->close();
取消链接('inner.zip');
$file_name=basename(“my.zip”);
标题(“内容类型:应用程序/zip”);
标题(“内容处置:附件;文件名=$file_name”);
标题(“内容长度:”.filesize(“my.zip”);
readfile(“my.zip”);
取消链接(“my.zip”);
出口
}否则{
echo“未能创建my.zip”;
}
}否则{
echo“未能创建内部.zip”;
}

对上述示例进行了测试,对于3个文件中的55Mb数据,生成的输出是一个约300Kb的压缩文件。虽然我决定用另一种方法解决这个问题,但我还是想把它贴出来。但仅供将来参考,这可能对某些人有所帮助

<?php
$zip_header_outer = "\x1f\x8b\x08\x08i\xbb\xb9X\x00\xffinner.zip\x00";
$zip_header_inner = "\x1F\x8B\x08\x08\x69\xBB\xB9\x58\x00\xFF";
$compression_level = 0;
$download_headers = true;
$download_file_name = 'my.zip';
$inner_file_name = 'inner.zip';
$first_level_file = 'a.txt';
$second_level_file = 'b.txt';


$fout = fopen("php://output", "wb");
if ($fout === FALSE) {
    die('Problem outputting');
}

if ($download_headers) {
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"" . $download_file_name . "\"");
}

function add_to_inner_zip($filename, $path, &$fout, &$fsize_outer, &$hctx_outer) {
    $zip_header_inner = "\x1F\x8B\x08\x08\x69\xBB\xB9\x58\x00\xFF";

        fwrite($fout, $zip_header_inner);
        hash_update($hctx_outer, $zip_header_inner);
        $fsize_outer += strlen($zip_header_inner);
        $hctx_inner = hash_init("crc32b");
        $fsize_inner = 0;

        // Inner Add file name
        $file_name = str_replace("\0", "", basename($filename));
        $data = $file_name."\0";
        fwrite($fout, $data, 1+strlen($data));
        hash_update($hctx_outer, $data);
        $fsize_outer += strlen($data);

        // Start inner.zip contents
            // Inner Add file data * STREAM CHUNKS HERE * 
            $file_data = file_get_contents($path);
            $clen = strlen($file_data);
            hash_update($hctx_inner, $file_data);
            $fsize_inner += $clen;
            /*hash_update($hctx_member, $file_data);
            $fsize_member += $clen;*/

            // Actually encode the chunk and add to the main stream
            $gziped_chunk = zlib_encode($file_data, ZLIB_ENCODING_RAW);
            fwrite($fout, $gziped_chunk);
            hash_update($hctx_outer, $gziped_chunk);
            $fsize_outer += strlen($gziped_chunk);

        // Close the inner zip 
    $crc = hash_final($hctx_inner, TRUE);
    $zip_footer = $crc[3].$crc[2].$crc[1].$crc[0] . pack("V", $fsize_inner);
    fwrite($fout, $zip_footer);

    // update outer crc + size
    hash_update($hctx_outer, $zip_footer);
    $fsize_outer += strlen($zip_footer);
}


// Outer
fwrite($fout, $zip_header_outer);
$fltr_outer = stream_filter_append($fout, "zlib.deflate", STREAM_FILTER_WRITE, $compression_level);
$hctx_outer = hash_init("crc32b");
$fsize_outer = 0;

    add_to_inner_zip($first_level_file, $first_level_file, $fout, $fsize_outer, $hctx_outer);
    
stream_filter_remove($fltr_outer);
$crc = hash_final($hctx_outer, TRUE);
fwrite($fout, $crc[3].$crc[2].$crc[1].$crc[0], 4);
fwrite($fout, pack("V", $fsize_outer), 4);

为什么不为你工作?@AlexBlex,你什么意思?我也没有空间放compelte文件,这就是为什么我必须流式处理它。你需要存储inner.zipsomewhere@AlexBlex,这就是我问这个问题的原因,我知道这并不常见,但我认为这是可能的。我没有压缩内部的zip文件,所以我确信这只是我必须处理第一个zip文件的头文件,但我很难做到这一点。这很公平,但不是那么简单。您正在询问如何将内部zip的输出流添加到
zip->addFileFromStream
,这需要并行运行两个zip。zip文件的格式比“仅仅是标题”要复杂一些。您可以在
ZipStream::addLargeFile
中检查它是如何计算的。您在哪里传输数据?我无法将文件存储在内存或硬盘中(我需要使用缓冲区发送)@funerr我理解这个示例是用于将文件放在本地,并在下载后删除它们。我能问点事吗?您是否从url流式传输,内容基本上是一个.txt文件。你能更具体地说明a.txt、b.txt、c.txt的位置吗?另外,你所说的
内存中不能有文件是什么意思?我可以理解HD部分,这意味着您不想将它们存储在本地,好的,上面的示例不这样做。即使在重新流式传输某些内容时,您不需要使用服务器的一部分内存吗?@funerr据我所知,您希望这样做,但它仅用于一个文件是的,但比这更复杂。我已经设法用ZipStream来传输文件,但我需要在zip中传输zip,并在运行中完成所有这一切,这相当困难。@funerr ZipStream使用Zlib函数。我将尝试编辑我的答案并发布一个可靠的示例(至少在本地测试),我希望在此之前您能得到更多答案。
<?php
$zip_header_outer = "\x1f\x8b\x08\x08i\xbb\xb9X\x00\xffinner.zip\x00";
$zip_header_inner = "\x1F\x8B\x08\x08\x69\xBB\xB9\x58\x00\xFF";
$compression_level = 0;
$download_headers = true;
$download_file_name = 'my.zip';
$inner_file_name = 'inner.zip';
$first_level_file = 'a.txt';
$second_level_file = 'b.txt';


$fout = fopen("php://output", "wb");
if ($fout === FALSE) {
    die('Problem outputting');
}

if ($download_headers) {
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"" . $download_file_name . "\"");
}

function add_to_inner_zip($filename, $path, &$fout, &$fsize_outer, &$hctx_outer) {
    $zip_header_inner = "\x1F\x8B\x08\x08\x69\xBB\xB9\x58\x00\xFF";

        fwrite($fout, $zip_header_inner);
        hash_update($hctx_outer, $zip_header_inner);
        $fsize_outer += strlen($zip_header_inner);
        $hctx_inner = hash_init("crc32b");
        $fsize_inner = 0;

        // Inner Add file name
        $file_name = str_replace("\0", "", basename($filename));
        $data = $file_name."\0";
        fwrite($fout, $data, 1+strlen($data));
        hash_update($hctx_outer, $data);
        $fsize_outer += strlen($data);

        // Start inner.zip contents
            // Inner Add file data * STREAM CHUNKS HERE * 
            $file_data = file_get_contents($path);
            $clen = strlen($file_data);
            hash_update($hctx_inner, $file_data);
            $fsize_inner += $clen;
            /*hash_update($hctx_member, $file_data);
            $fsize_member += $clen;*/

            // Actually encode the chunk and add to the main stream
            $gziped_chunk = zlib_encode($file_data, ZLIB_ENCODING_RAW);
            fwrite($fout, $gziped_chunk);
            hash_update($hctx_outer, $gziped_chunk);
            $fsize_outer += strlen($gziped_chunk);

        // Close the inner zip 
    $crc = hash_final($hctx_inner, TRUE);
    $zip_footer = $crc[3].$crc[2].$crc[1].$crc[0] . pack("V", $fsize_inner);
    fwrite($fout, $zip_footer);

    // update outer crc + size
    hash_update($hctx_outer, $zip_footer);
    $fsize_outer += strlen($zip_footer);
}


// Outer
fwrite($fout, $zip_header_outer);
$fltr_outer = stream_filter_append($fout, "zlib.deflate", STREAM_FILTER_WRITE, $compression_level);
$hctx_outer = hash_init("crc32b");
$fsize_outer = 0;

    add_to_inner_zip($first_level_file, $first_level_file, $fout, $fsize_outer, $hctx_outer);
    
stream_filter_remove($fltr_outer);
$crc = hash_final($hctx_outer, TRUE);
fwrite($fout, $crc[3].$crc[2].$crc[1].$crc[0], 4);
fwrite($fout, pack("V", $fsize_outer), 4);