Bonjour,

Dans un script j'effectue une compression bz2 à la volée pour envoyer un fichier déjà compressé au client.
Dans Symfony2 j'utilise ce code dans un service :

Code php : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php
 
namespace Acme\ExportTableBundle\Services;
 
use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Component\HttpFoundation\StreamedResponse;
 
class PackageTable
{
    public function __construct(Registry $doctrine)
    {
        $this->doctrine = $doctrine;
    }
 
    public function package($fqn_table)
    {
 
        list($database, $table) = explode('.', $fqn_table);
 
        $connection = $this->doctrine->getConnection($database);
        $user = $connection->getUsername();
        $password = $connection->getPassword();
 
        $proc = proc_open(
            "mysqldump -u $user -p $database $table",
            array(
                0 => array('pipe', 'r'),
                1 => array('pipe', 'w')
            ),
            $stream
        );
 
        if (is_resource($proc)) {
            fwrite($stream[0], $password);
            fclose($stream[0]);
 
            $dump = $stream[1];
 
            flush();
            ob_clean();
 
            $response = new StreamedResponse;
            $response->setCallback(function () use ($dump) {
 
                rewind($dump);
 
                $output = fopen('php://output', 'w+');
 
                while (!feof($dump)) {
                    $chunk = fread($dump, 8192);
                    fwrite($output, bzcompress($chunk));
 
                    if (empty($chunk)) {
                        break;
                    }
                }
 
                fclose($dump);
            });
 
            $response->setStatusCode(200);
 
            $response->headers->set('Content-Description', 'File Transfer');
            $response->headers->set('Content-Type', 'application/x-bzip2');
            $response->headers->set('Content-Transfer-Encoding', 'binary');
            $response->headers->set('Content-Disposition', "attachment; filename=$table.sql.bz2");
 
//            return $response;
            $response->send();
        }
    }
}

L'erreur qui apparait est :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
Warning: rewind(): 20 is not a valid stream resource
Un var_dump sur $dump montre que la resource est de type "unknown".

J'ai donc essayé le code suivant (dont le cœur est identique) pour dégager les responsabilités :

Code php : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
 
use Symfony\Component\HttpFoundation\StreamedResponse;
 
require '../vendor/autoload.php';
 
$fqn_table = 'database_reference_backups.toto_short';
 
$user = 'root';
$password = '*';
 
list($database, $table) = explode('.', $fqn_table);
 
$proc = proc_open(
    "mysqldump -u $user -p $database $table",
    array(
        0 => array('pipe', 'r'),
        1 => array('pipe', 'w')
    ),
    $stream
);
 
if (is_resource($proc)) {
    fwrite($stream[0], $password);
    fclose($stream[0]);
 
    $dump = $stream[1];
 
    $response = new StreamedResponse;
    $response->setCallback(function () use ($dump) {
 
        $output = fopen('php://output', 'w+');
 
        while (!feof($dump)) {
            $chunk = fread($dump, 8192);
 
            fwrite($output, bzcompress($chunk));
 
            if (empty($chunk)) {
                break;
            }
        }
 
        fclose($dump);
    });
 
    $response->setStatusCode(200);
 
    $response->headers->set('Content-Description', 'File Transfer');
    $response->headers->set('Content-Type', 'application/x-bzip2');
    $response->headers->set('Content-Transfer-Encoding', 'binary');
    $response->headers->set('Content-Disposition', "attachment; filename=$table.sql.bz2");
 
    $response->send();
}

Ce code exécuté seul, fonctionne parfaitement.

Je trouve cela extrêmement étrange, mais visiblement symfony y est pour quelque chose.

Any guess ?