Forums

Saving User Edited PDF

Hello all! I have an iframe with a pdf url inside it that displays pdf files stored in the PythonAnywhere filesystem. The goal is to be able to have the user edit the PDF, then save the modified PDF to its online location with the user's modifications.

I have tried using something like this:

function saveModifiedPdf(code) {
        const pdfIframe = document.getElementById('pdfIframe');
        const modifiedPdfUrl = pdfIframe.src;


        fetch(modifiedPdfUrl)
            .then(response => response.blob())
            .then(pdfBlob => {

                const formData = new FormData();
                formData.append('code', code);
                formData.append('pdf', pdfBlob, 'code.pdf');

                console.log('Modified PDF Blob size:', pdfBlob.size);
                console.log('Modified PDF Blob type:', pdfBlob.type);

                const savePdfUrl = `/save-pdf/${code}`;

                fetch(savePdfUrl, {
                    method: 'POST',
                    body: formData,
                    headers: {
                        'Content-Type': 'application/pdf'
                    }
                })
                .then(response => {
                    if (response.status === 200) {
                        console.log('Modified PDF saved successfully!');
                    } else {
                        console.error('Failed to save modified PDF.');
                    }
                })
                .catch(error => {
                    console.error('Error:', error);
                });
            })
            .catch(error => {
                console.error('Error fetching modified PDF:', error);
            });
    }

The python route looks like this:

@app.route('/save-pdf/<code>', methods=['POST'])
def save_pdf(code):
     # Get the modified PDF data from the request
     modified_pdf_data = request.data

    with open(f'/route/to/file.pdf', 'wb') as file:
        file.write(modified_pdf_data)

However it appears that this method doesn't retrieve the user modified data from the pdf. I believe the reason is because the code is pulling information from the url, which hasn't been updated with the user's changes.

Does anyone have any idea how to save a file with user edits to a file inside the PythonAnywhere system?

Thanks!

I think you're entirely right about why that's not working; the user is making the changes to a copy in the browser, but your saveModifiedPdf function is just getting the original unmodified version from the URL and saving it.

I don't know of any way to extract a modified PDF from the browser, but perhaps if you post on Stack Overflow you might find someone that knows how?

Alright, thanks Giles I appreciate it.

I was just wondering if anyone had information here first since it's kind of specific.

It seems like there should be a library for this, but I can't seem to find anything about this.

I think it's the kind of problem that would be the same regardless of whether you were running it on PythonAnywhere or on another server. I have to agree, though, it does feel like the kind of problem that other people would have had in the past!

Finally was able to hack together a solution, which I will put the essence of here so if anyone else has this problem they can find it.

You have to use a modified PDFTron (now Apryse) library.

Sign up for Apryse with this link: https://docs.apryse.com/try-now/

Download the PDFTron WebViewer from this link: https://docs.apryse.com/documentation/web/download/#webviewer

Now you have to extract the folder.

Pull the core folder (located at WebViewer/lib/core) out of the lib folder. The reason why is it's too big to be uploaded in one go, so you have to modify it.

Zip up both folders, then upload the WebViewer folder to your static directory. If you don't upload it to the static directory, I've found that the folders can't be found by their URL.

Move the core folder back into the lib folder by navigating to the lib folder and uploading the zipped core folder there.

Now, you have to modify the WebViewer.min.js file to accommodate for the change in position. You can find this file in the lib folder. Find the line: this.options.uiPath=this.options.path+this.options.uiPath or this.options.uiPath = this.options.path + this.options.uiPath. Replace this line with this: this.options.uiPath = "/static/WebViewer/" + this.options.uiPath. This will allow the path to be modified to the correct one, given our change in path.

After this, you can display your PDF file according to the documentation here: https://docs.apryse.com/documentation/web/guides/basics/open/url/. See the saving documentation for how to acquire the modified pdf blob. Send that to your server with some processing code and that should be it!

Hopefully this can help someone else out.

Thanks for letting us know!