WebHU - Programozási kérdések és válaszok

A react-pdf megvalósítása nyomtatási funkcióval

Szeretném a react-pdf-et használni a PDF megjelenítéséhez, és egy nyomtatási funkciót szeretnék kifejleszteni a közvetlen nyomtatáshoz (például a window.print() használatával);

A REST szervert Jersey felhasználásával fejlesztették ki.

A PDF generálódik a szerverről, és visszatér a React klienshez a Jersey használatával, a visszaküldési típus: application/pdf. A React kliens a react-pdf használatával jeleníti meg a PDF-fájlt.

Nem szeretném deklarálni az URL elérési útját a fájlban, mert ez újra lekéri a PDF-fájlt a szerverről, ha a React állapot megváltozik és újrarenderelést vált ki. Ezenkívül ki kell fejlesztenem egy nyomtatási funkciót a megjelenített PDF kinyomtatásához (mert a PDF tartalom megváltozhat, ha újra lekéri a PDF-et a szerverről)

Alább mutasd meg a kódomat:

Szerver:

@Override
@GET
@Path("/pdf")
@Produces(MediaType.APPLICATION_PDF_VALUE)
public Response testPdf() throws Exception {

    File file = new File("C:\\Desktop\\test.pdf");
    FileInputStream fileInputStream = new FileInputStream(file);
    
    ResponseBuilder response = Response.ok((Object) fileInputStream);
    response.type("application/pdf");
    response.header("Content-Disposition", "filename=test.pdf");
    
    return response.build();
}

Ügyfél

import React, { Component } from 'react';
import { Document, Page } from 'react-pdf';
import axios from 'axios';

class MyApp extends Component {
    state = {
        numPages: null,
        pageNumber: 1,
        pdfContent: null
    }

    componentDidMount(){
        var that = this;

        axios.get("url\Pdf").then((response) => {
             that.setState({pdfContent:response.data});
        }).catch((error) => {
             console.warn(error);
        });
    }

    onDocumentLoadSuccess = ({ numPages }) => {
        this.setState({ numPages });
    }

    printHandler(){
        window.print();
    }

    render() {
        const { pageNumber, numPages } = this.state;

        return (
            <div>
                <Document
                    file={this.state.pdfContent}
                    onLoadSuccess={this.onDocumentLoadSuccess}
                >
                    <Page pageNumber={pageNumber} />
                </Document>
                <p>Page {pageNumber} of {numPages}</p>

                <button onClick={() => this.setState(prevState => ({ 
                        pageNumber: prevState.pageNumber + 1 }))}>Next page</button>
                <button onClick={() => this.setState(prevState => ({ 
                        pageNumber: prevState.pageNumber - 1 }))}>Prev Page</button>

                <button onClick={this.printHandler}/>
            </div>
        );
    }
}

Csak egyszer szeretném beszerezni a PDF-et, és a react-pdf használatával megjeleníteni. Ezenkívül ki szeretném nyomtatni a megjelenített PDF-et.

Megpróbáltam konvertálni a response.data fájlt base64-re, ezt a sort követtem, mert nem sikerült: (ezzel elveszik a pdf tartalom) PDF kódolása base64-be ReactJS-ben

Kód, mint:

    componentDidMount(){
        var that = this;

        axios.get("url\Pdf").then((response) => {
            let reader = new FileReader();
            var file = new Blob([response.data], { type: 'application/pdf' });

            reader.onloadend = () => {
                that.setState({
                    base64Pdf:reader.result
                });
            }
            reader.readAsDataURL(file);
        }).catch((error) => {
             console.warn(error);
        });
    }

Tud valaki valami javaslatot adni? Vagy van valami jobb módszer a célom eléréséhez?

Kösz


  • Mit próbáltál eddig? 30.12.2018
  • @Mikkel Megpróbáltam a FileReaderrel a base64-re válaszolni. Azonban még mindig nem jártam sikerrel (talán nem ismerem ezt...) Frissítettem néhány kódot a bejegyzésemhez. 30.12.2018

Válaszok:


1

Frissítés a háttérből érkező hibaüzenetről:

Ha egy kérés sikertelen, egy JSON-objektumot kapunk a háttértől, amely tartalmazza a hibaüzenetet. A probléma az, hogy amikor a választ blob formátumban kényszerítjük: responseType: 'blob' - függetlenül attól, hogy a kérés sikertelen vagy sem, egy Blob objektumot kapunk. Tehát azon gondolkodtam, hogy az axios: transformResponse függvényben módosítsuk a responseType-ot, de sajnos nem férünk hozzá a 'responseType' objektumhoz, csak a fejlécekhez. Itt: https://github.com/axios/axios/pull/1155 ott nyitott probléma a választípusra való konvertálással kapcsolatban, még mindig nem oldódott meg.

Tehát a probléma megoldásának módja a fetch használata az axiók helyett. Íme egy példa:

fetch('here.is.your/endpoint', {
            method: 'POST', // specifying the method request
            body: JSON.stringify(request), // specifying the body
            headers: {
                "Content-Type": "application/json"
            }
        }
    ).then((response) => {
        if (response.ok) { // checks if the response is with status 200 (successful)
            return response.blob().then(blob => {
                const name = 'Report.pdf';
                saveAs(blob, name);
            });
        } else {
            return response.json().then((jsonError) => {
                this.setState({
                    modalMessage: jsonError.message // access the error message returned from the back-end
                });
            });
        }
    }).catch(function (error) {
        this.setState({
            modalMessage: "Error in data type received." // general handler
        });
    });

Remélem ez segít!

04.02.2019

2

Nemrég kaptam egy hasonló használati esetet a pdf résszel, a kérésem a Post, de gond nélkül meg tudod szerezni. Szóval, mi történik:

1) - Az axios szolgáltatást használom a háttérbe irányuló kéréshez:

2) - A request az az objektum, amelyet küldök, de neked nem lesz ilyen, mivel valószínűleg csak azonosítót fogsz küldeni, például: axios.get('here.is.your/endpoint/ id');

3) - A kapott fájl mentésére a file-saver-t használom.

A kód többi részének magától értetődőnek kell lennie, és néhány megjegyzést is tettem hozzá.

import {saveAs} from "file-saver";
...

axios.post('here.is.your/endpoint', qs.parse(request), {
       headers: {
          'Content-Type': 'application/json'
       },   
       responseType: 'blob' // here I am forcing to receive data in a Blob Format
    })
    .then(response => {
        if (response.data) {
            //Create a Blob from the PDF Stream
            const file = new Blob(
                [response.data],
                {type: 'application/pdf'});
            const name = 'Report.pdf';
            saveAs(file, name);
        } else {
            throw new Error("Error in data type received.");
        }
    })
    .catch(error => {
        this.setState({
            modalMessage: "Here Add Custom Message"
        });
   });

A hibaüzenetet továbbra sem tudom megkapni a háttérből, vissza fogok küldeni, ha lesz valami előrelépés a dologban - egyelőre egyéni üzenetet mutatok.

Remélem ez segít!

Sok szerencsét!

04.02.2019

3

Örülök, hogy segítettem!

Van még egy FRISSÍTÉSEM A HIBAÜZENET KÉPÉSÉHEZ

EZ CSAK AKKOR ÉRVÉNYES, HA SZÖVEZETES ÜZENETET KAP, NEM JSON

fetch('here.is.your/endpoint', {
        method: 'POST', // specifying the method request
        body: JSON.stringify(request), // specifying the body
        headers: {
            "Content-Type": "application/json"
        }
    }
).then((response) => {
    if (response.ok) { // checks if the response is with status 200 (successful)
        return response.blob().then(blob => {
            const name = 'Report.pdf';
            saveAs(blob, name);
        });
    } else {
         return response.text().then(function (error) {
                    throw new Error(error); // we should throw an Error with the received error
                }
            );
    }
}).catch(function (error) {
    this.setState({
        modalMessage: error.message // that way we access the error message
    });
});

A response.text().then()-et használjuk, mert így sikerül Promise-ból szöveggé konvertálni. És fontos a .then() használata, mert az Ígéret abban a pillanatban megoldódott, és megkapjuk az ígéret értéket. Ekkor egyszerűen kidobunk egy Error-t, mert nem férünk hozzá az állapotobjektumhoz.

Így kapsz szöveget a válaszból.

21.03.2019
Új anyagok

A rádiógomb ellenőrzött eseményének használata a jQueryben
Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

Miért érdemes elkezdeni a kódolást 2023-ban?
01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

🎙 Random Noise #2  – Örökbefogadás és hit
az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..