-1

我正在尝试使用 Symfony 5 发送生成的 CSV 文件,但不知何故似乎已经达到了我无法克服的限制。出于测试原因,我将其分解为基础知识;所以我发送静态数据,生成一个 txt 文件并且不做任何逻辑。在下面的示例代码中,如果我进行 65 次迭代,则会生成文件并将其作为下载文件发送到浏览器(即 4KB)。如果我执行 66 或向 $data 示例数据字符串添加一个字母,则它全部显示在浏览器窗口中。即使迭代 1000 次,完全相同的代码在 Symfony 之外也能完美运行。我也没有从 dev.log 中得到任何可以提供帮助的错误或任何内容。

public function saveCSV(Request $request, DelcampeParser $parser) {
    $response = new Response();

// same with
//  $response = new StreamedResponse();
//  $response->setCallback(function(){});

    $response->headers->set('Content-Type', 'text/plain; charset=utf-8');
    $disposition = HeaderUtils::makeDisposition(
        HeaderUtils::DISPOSITION_ATTACHMENT,
        'foo.txt'
    );
    $response->headers->set('Content-Disposition', $disposition);

    $data = array(0 => 'abcdefghijklmnopqrstuvwxyz');
    for ($a=1;$a<=66;$a++) {
        var_dump($data);
    }

    return $response;
}

怎么了?为什么我无法在 Symfony 中生成更大的文件?

谢谢你。

[编辑] 我有一个新理论:PHP 的输出缓冲设置为 4KB。只要缓冲区已满,缓冲的数据就会发送到浏览器。不幸的是,这发生在 Symfony 发送标头之前,从而生成浏览器输出。我怎样才能改变这种行为?

4

1 回答 1

0

我现在有了 StreamedResponse 的答案,它可以工作,并且希望也能满足 Symfony 的所有要求和建议:

// in the Controller
public function saveCSV(Request $request, Parser $parser) {
    $response = new StreamedResponse();

    $data = $request->get("sd");    // sd comes out of a form that posts a multidimensional array
    $response->setCallback(function() use ($data, $parser) {
        $parser->generateCSV($data);
    });

    $response->headers->set('Content-Type', 'text/csv; charset=utf-8');
    $disposition = HeaderUtils::makeDisposition(
        HeaderUtils::DISPOSITION_ATTACHMENT,
        "delcampeimport_".date("Ymd-Hi").".csv",
    );
    $response->headers->set('Content-Disposition', $disposition);

    return $response;
}

和我的服务

public function generateCSV($dataarray) {
    $out = fopen('php://output', 'w+');

    // send header rows of csv file
    fputs($out, "website_visibility,category_id,title, /* ..., */ images\r\n");

    // generate data
    foreach($dataarray AS $stamp) {
        $stampdata = array ( 
            'a' => 'CH',
            'b' => $stamp['category'],
            'c' => htmlentities($stamp['title']),
            // ...
            'aa' => $stamp['img1'].
            ($stamp['img2'] ? ";".$stamp['img2']:"").
            ($stamp['img3'] ? ";".$stamp['img3']:"")
        );

        // send csv data
        fputcsv($out, $stampdata);
    }
    fclose($out);
}

感谢您的投入

于 2020-01-23T16:33:52.607 回答