Создать PDF и вернуть ответ

Сегодня я столкнулся с проблемой создания PDF с помощью KnpSnappyBundle на symfony.

Я запускаю маршрут с использованием AJAX, код работает нормально, но не создает PDF,

Здесь я хочу создать PDF-файл в новой вкладке или окне и вернуть клиенту успешное сообщение.

Вот мой код:

 /**
 * @Route("/api/release_bills/{month}/{year}/{region}", name="api_print_bills", methods={"GET","POST"})
 * @param BillRepository $billRepository
 * @param ConsumptionRepository $consumptionRepository
 * @param Request $request
 * @param Snappy $snappy
 * @param $month
 * @param $year
 * @param $region
 * @return Response
 * @throws Exception
 */
public function releaseBills(BillRepository $billRepository,ConsumptionRepository $consumptionRepository, Request $request, Snappy $snappy,  $month,$year,$region ): Response
{
    $error = array();
    $success = array();
    if( $month>0 && $month<13 || preg_match("/^\d{4}$/",$year)||$region!=''){

        if($year>=2018 && $year <=2050){
            $entityManager = $this->getDoctrine()->getManager();

                $bills = $consumptionRepository->findAllWaterMetersForBilling($month,$year,$region);

                $isBillsExisted = $billRepository->findAllBillsByDate($month,$year,$region);

                if(empty($bills)){
                    array_push($error,['error'=>'there is not bills to be release for this criteria : [ city: '.$region.', year :'.$year.', and Month : '.$month.'!]']);
                    return new JsonResponse($error);
                }

                $arr = array();
                $newBills = array();
                $billsEnd=end($bills);

                foreach ($bills as $key=>$b){
                    $wmNumber =  $b->getWaterMeter()->getWmNumber();
                    $fullName = $b->getWaterMeter()->getClient()->getFullName();
                    $cin = $b->getWaterMeter()->getClient()->getCin();
                    $address= $b->getWaterMeter()->getAddress();
                    $wmAddress = $b->getWaterMeter()->getAddress()->getStreetAddress();
                    $city = $b->getWaterMeter()->getAddress()->getCity();
                    $zipCode = $b->getWaterMeter()->getAddress()->getZipCode();
                    $billCode = $b->getId();
                    $consumptionDate = $b->getDate();
                    $oldConsumption=$b->getPreviousRecord();
                    $newConsumption=$b->getCurrentRecord();
                    $printDate =new \DateTime('now');
                    $consumption=$b->getConsumption();
                    $cost = $b->getCost()+10;
                    $wmReferenceNumber = $b->getWaterMeter()->getWmReferenceNumber();
                    $client= $b->getWaterMeter()->getClient();
                    // tranche calculation
                    //==================================================
                    $tranche1 = $consumption >= 5 ? 5 : $consumption; //4
                    $tranche2 = $consumption - $tranche1 >= 5 ? 5: 0; //0
                    $tranche3 = $consumption - $tranche1 - $tranche2;
                    //==================================================
                    $bill = new Bill();
                    $bill->setCode($wmNumber);
                    $bill->setFullName($fullName);
                    $bill->setCin($cin);
                    $bill->setPrintDate($printDate);
                    $bill->setCost($cost);
                    $bill->setConsumption($consumption);
                    $bill->setConsumptionDate($consumptionDate);
                    $bill->setPreviousRecord($oldConsumption);
                    $bill->setNewRecord($newConsumption);
                    $bill->setWaterMeter($b->getWaterMeter());
                    $bill->setRegion($city);
                    $bill->setClient($client);
                    $entityManager->persist($bill);
                    array_push($arr,['wmAddress'=>$wmAddress,'city'=>$city,'zipCode'=>$zipCode,'tranche1'=>$tranche1,'wmNumber'=>$wmNumber,'fullName'=>$fullName,'cin'=>$cin,'address'=>strval($address),'billCode'=>$billCode,'consumptionDate'=>$consumptionDate,'oldConsumption'=>$oldConsumption,'newConsumption'=>$newConsumption,'printDate'=>$printDate,'consumption'=>$consumption,'cost'=>$cost,'wmReferenceNumber'=>$wmReferenceNumber]);

                    if(count($arr)==6||$billCode==$billsEnd->getId()){
                        array_push($newBills,$arr);
                        $arr = array();
                    }

                }

                $date = new \DateTime('now');
                $html= $this->renderView('bill/bill.html.twig', array(
                    'arrayBills'=>$newBills,
                ));


                if($isBillsExisted){
                    return new PdfResponse(
                        $snappy->getOutputFromHtml($html), "bill_".$date->format('Y-m-d').".pdf"
                    );
                }
                $entityManager->flush(); //Persist objects that did not make up an entire batch
                $entityManager->clear();

                return new PdfResponse(
                    $snappy->getOutputFromHtml($html), "bill_".$date->format('Y-m-d').".pdf"
                );

            }
        }
    array_push($success,['success'=>'bills were successfully released']);
    return new JsonResponse($success);
}

И мой вызов AJAX:

 generatePDF = () =>{ 
        const {yearValue, monthValue, regionValue}= this.state;
        $.ajax({
            url: `http://symfony.localhost/bill/api/release_bills/${monthValue.value}/${yearValue.value}/${regionValue.value}`,
            success: function (data) {
                console.log('DATA',data)
            }.bind(this)
        });
    };

Я считаю, что я не могу вернуть более одного ответа, в любом случае я сделал журнал консоли, чтобы ответ на вызов ajax отображал HTML-содержимое страницы, из которой я хочу создать PDF, и PDF не создается.


person Mohamed Aarab    schedule 17.02.2020    source источник


Ответы (3)


Это, вероятно, позже, но вы можете попробовать так:

    $file = $folder . $fileName ;

    if (is_file($file)) {
        unlink($file);
    }

Затем вы создаете и сохраняете свой файл с тем же именем и позже. Не используйте return new PdfResponse..., но

$pdf->generateFromHtml($html, $folder . $file);

а затем вернуть ответ

    $response = new JsonResponse();
    $response->setStatusCode(Response::HTTP_NOT_FOUND); // 404
    if (is_file($file)) {
        $response->setStatusCode(Response::HTTP_OK); // 200
    }
person francoisV    schedule 08.10.2020

попробуйте изменить Ajax следующим образом:

$.ajax({
  url: `http://symfony.localhost/bill/api/release_bills/${monthValue.value}/${yearValue.value}/${regionValue.value}`,
  success: function(data) {
    var blob=new Blob([data]);
    var link=document.createElement('a');
    link.href=window.URL.createObjectURL(blob);
    link.download="<CHOOSE_FILENAME_WITH_EXTENSION>";
    link.click();
  }
});
person Nobady    schedule 17.02.2020
comment
я попробовал как вы посоветовали, но не работает, все равно спасибо - person Mohamed Aarab; 17.02.2020

с помощью друга мне удалось сгенерировать pdf, но я все еще не знаю, как вернуть сообщение об ошибке или успешном завершении, когда pdf сгенерирован или нет.

вот что я сделал:

generatePDF = () =>{
    const {yearValue, monthValue, regionValue}= this.state;

    var strWindowFeatures = "location=yes,height=570,width=520,scrollbars=yes,status=yes";
    var URL = `http://symfony.localhost/bill/api/release_bills/${monthValue.value}/${yearValue.value}/${regionValue.value}`;
    window.open(URL, "_blank", strWindowFeatures);
};

функция generatePDF вызывается на кнопке onClick

person Mohamed Aarab    schedule 17.02.2020