Send file with response body


#1

Hello, I’m trying to send a file through the API response and download it using Guzzle for a web app project, the problem is that when I try to save the file the size is always 0 bytes. Is this approach missing something?

API Code

    if ($document[0]->exists) {
                $payload[] = $document[0]->fileOutput();
                $file = $document[0]->file_url;
                $openFile = fopen($file, 'rb');
                $stream = new \Slim\Http\Stream($openFile);
                return $response->withStatus(200)
                    ->withHeader('Content-Type', 'application/force-download')
                    ->withHeader('Content-Type', 'application/octet-stream')
                    ->withHeader('Content-Type', 'application/download')
                    ->withHeader('Content-Description', 'File Transfer')
                    ->withHeader('Content-Transfer-Encoding', 'binary')
                    ->withHeader('Content-Disposition', 'attachment; filename="' . basename($file) . '"')
                    ->withHeader('Expires', '0')
                    ->withHeader('Content-Length', filesize($file))
                    ->withHeader('Cache-Control', 'must-revalidate')
                    ->withHeader('Pragma', 'public')
                    ->withBody($stream)
                    ->withJson([
                        'message' => 'Success',
                        'code' => 204,
                        'documents' => $payload
                    ]);
            } 

Web App Code

 public function requestFile($path)
    {
        $credentials = BaseMiddleware::getToken();
        try {
            $this->api_response = $this->client->get(
                $this->api_address . $path, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $credentials
                ],
            ]);
        } catch (ServerException $server_exception) {
            $this->api_response = $server_exception;
        } catch (ClientException $client_exception) {
            $this->api_response = $client_exception;
        } catch (BadResponseException $response_exception) {
            $this->api_response = $response_exception;
        }

        return $this->api_response;
    }
  public function requestDocumentAttachment($request, $response, $args)
    {
        $path = "/documents/" . $args['document_id'] . '/attachment';
        $api_request = $this->requestFile($path);
        if (method_exists($api_request, 'getCode')) {
            $result = $api_request;
            $result_code = $result->getCode();
        } else {
            $result = $api_request->getBody()->getContents();
            $result_code = json_decode($result)->code;
        }

        if ($result_code == 204) {
            // need to figure out how to download file correctly, currently the download size is zero.
            return $api_request;

        } else if ($result_code == 500) {
            $_SESSION['result_error'] = "Invalid request, try again";
        } else if ($result_code == 401) {
            $_SESSION['result_error'] = "Not authorized";
        }
    }

#2
->withBody($stream)
->withJson([

Calling withJson after withBody will overwrite the the last response body, in this case the file stream.


#3

Oh, Thanks odan, that was the problem. Now I’m able to download the file now. I also had to add 'stream' => true in the request file method.