Guzzle 6 Large file uploads / Chunking

人走茶凉 提交于 2020-01-07 04:30:54

问题


I've read that if Guzzle cannot determine Content-Length, it will send Transfer-Encoding: Chunked headers and cURL on the back-end will handling the chunking. But I'm obviously hitting post_max_size limit. ("POST Content-Length of 524288375 bytes exceeds the limit of 8388608 bytes) when POSTing to a working uploadChunkerController. I know the upload handler (endpoint) works with smaller files. I feel I have something configured wrong with my Guzzle options. I have to set verify to false and I need to post an api_key with the request.

    $client = new Client();
    $fh     = fopen('../storage/random-500M.pdf', 'r');
    $url    = 'https://local:8443/app_dev.php/_uploader/bigupload/upload';

    $request = $client->request(
        'POST',
        $url,
        [
            'verify'    => false,
            'multipart' => [
                [
                    'name' => 'api_key',
                    'contents' => 'abc123'
                ],
                [
                    'name'     => 'file',
                    'contents' => $fh,
                    'filename' => 'bigupload.pdf'
                ]
            ]
        ]
    );

Editing php.ini settings is not an option nor the solution. I've found a lot of 'solutions' that appear to be for older versions of Guzzle. Am I thinking too hard about this? Is there a simpler solution?


回答1:


After digging through Guzzle and cURL source code, there's no 'automatic' way for them to send 'chunks'. Headers aren't set and there's no way for them to slice up the file being sent. I've come up with my own solution using Guzzle vs raw PHP cURL calls.

/**
 * @Route("/chunks", name="chunks")
 */
public function sendFileAction()
{
    $jar       = new \GuzzleHttp\Cookie\SessionCookieJar('SESSION_STORAGE', true);
    $handler   = new CurlHandler();
    $stack     = HandlerStack::create($handler);
    $client    = new Client(['cookies'=>true, 'handler' => $stack]);
    $filename  = 'files/huge-1gig-file.jpg';
    $filesize  = filesize($filename);
    $fh        = fopen($filename, 'r');
    $chunkSize = 1024 * 2000;
    $boundary  = '----iCEBrkUploaderBoundary' . uniqid();
    $url       = 'https://localhost/app_dev.php/_uploader/bigupload/upload';

    rewind($fh); // probably not necessary
    while (! feof($fh)) {
        $pos   = ftell($fh);
        $chunk = fread($fh, $chunkSize);
        $calc  = $pos + strlen($chunk)-1;

        // Not sure if this is needed.
        //if (ftell($fh) > $chunkSize) {
        //    $pos++;
        //}

        $request = $client->request(
            'POST',
            $url,
            [
                'cookies' => $jar,
                'debug'   => false,
                'verify'  => false,
                'headers' => [
                    'Transfer-Encoding'   => 'chunked',
                    'Accept-Encoding'     => 'gzip, deflate, br',
                    'Accept'              => 'application/json, text/javascript, */*; q=0.01',
                    'Connection'          => 'keep-alive',
                    'Content-disposition' => 'attachment; filename="' . basename($filename) . '"',
                    'Content-length'      => $calc - $pos,
                    'Content-Range'       => 'bytes ' . $pos . '-' . $calc . '/' . $filesize
                ],
                'multipart' => [
                    [
                        'name'     => 'api_key,
                        'contents' => 'aaabbbcc-deff-ffed-dddd-1234567890123'
                    ],
                    [
                        'name'     => 'file',
                        'contents' => $chunk,
                        'filename' => basename($filename),
                        'headers' => [
                            'Content-Type' => 'multipart/form-data; boundary=' . $boundary
                        ]
                    ]
                ]
            ]
        );
    }

    return new Response('ok', 200);
}

I hope this helps someone else out. Comments/Suggestions welcome.




回答2:


Chunked transfer encoding doesn't help in this case.

It's used to provide content ASAP by sending (and generating) it by parts. It has nothing to do with size limits (like in your scenario).

The only way for you is to increase the limit on the server.



来源:https://stackoverflow.com/questions/45641050/guzzle-6-large-file-uploads-chunking

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!