在两个Symfony2应用程序之间转发BinaryFileResponse

时间:2016-07-20 10:23:12

标签: symfony curl download httprequest api-design

我有两个Symfony应用程序(API)通过使用cURL PHP函数的HTTP请求/响应相互通信。这在获得小JSON响应时工作正常,但是在获取和提供文件时会出现问题。 API1(暴露于Internet)需要提供只能由API2访问的文件(私有,通过VPN连接到API1)。

如果我在第一个API中编码文件的内容然后在响应正文中传递它没有问题,我可以将文件重新转换回流并在第一个API中作为BinaryFileResponse提供。问题来自大文件(> 30MB),其中响应主体很大,symfony无法分配那么多内存。

有没有办法将BinaryFileResponse从一个API转发或重定向到另一个API,因此中间层对于客户端是不可见的?

这些是每个应用程序中的两段代码:

公共API:

Q: My site currently follows your recommendation and supports _escaped_fragment_. Would my site stop getting indexed now that you've deprecated your recommendation?
A: No, the site would still be indexed. In general, however, we recommend you implement industry best practices when you're making the next update for your site. Instead of the _escaped_fragment_ URLs, we'll generally crawl, render, and index the #! URLs.

私人API:

/**
 *
 * @Get("/api/login/getfile")
 */
public function testGetFilePrivate(Request $request)
{
    $url = 'private/variantset/9/getfile';
    $url = $this->container->getParameter('api2_url').$url;

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 300000); //Set timeout in ms
    $response = curl_exec($ch);
    curl_close($ch);
    $data = json_decode($response, TRUE);
    $fileContent = base64_decode($data['filedata']);
    $response = new Response($fileContent);

    $disposition = $response->headers->makeDisposition(
        ResponseHeaderBag::DISPOSITION_ATTACHMENT,
        $data['filename']
    );

    $response->headers->set('Content-Disposition', $disposition);
    return $response;
}

1 个答案:

答案 0 :(得分:1)

最后通过结合答案找到解决方案 Streaming a large file using PHPManipulate a string that is 30 million characters long

HTTP流包装器不是使用cURL PHP函数,而是用于捕获API2响应。这个包装器然后使用Symfony的StreamedResponse类解析输出:

    $response = new StreamedResponse(function() use($url) {
        $handle = fopen($url, 'r');
        while (!feof($handle)) {
            $buffer = fread($handle, 1024);
            echo $buffer;
            flush();
        }
        fclose($handle);
    });

    $response->headers->set('Content-Type', 'application/octet-stream');
    return $response;

我仍然在努力研究如何从初始请求中获取内容类型,如果我最终设法正确处理它,我将编辑响应。欢迎任何建议。