PDF is not saving in locally in flask server

Question:

im running a script that converts images to a pdf file and saves the pdf locally, it works on my windows machine, but on my flask server they arent saving.

here is the code



from cmath import e
from os import link
from pickle import GET
from webbrowser import get
from flask import Flask, render_template, request, jsonify , redirect, url_for
from flask import send_file
import json
import requests
from libgen_api import LibgenSearch
from kissmanga import get_search_results, get_manga_details, get_manga_episode, get_manga_chapter
import aiohttp
import aiofiles
import asyncio
import os
from fake_headers import Headers
from fpdf import FPDF
from PIL import Image
import glob
import uuid


app = Flask(__name__)




@app.route("/")
def home():
    return render_template(
        "index.html" 
    )

@app.route("/api/default")
def titleSearch():
    try:

        title = request.args.get('query')

    
        s = LibgenSearch()
        results = s.search_title(title)
        item_to_download = results[0]
        download_links = s.resolve_download_links(item_to_download)
        return render_template(
        "results.html", results=results, download_links=download_links, title=title, )

    except IndexError:
        return render_template(
        "error.html")
            
@app.route("/api/manga")
def mangasearch():
    try:
        class bcolors:
            HEADER = '33[95m'
            OKBLUE = '33[94m'
            OKCYAN = '33[96m'
            OKGREEN = '33[92m'
            WARNING = '33[93m'
            FAIL = '33[91m'
            ENDC = '33[0m'
            BOLD = '33[1m'
            UNDERLINE = '33[4m'
        
        InputMangaTitle = request.args.get('manganame')
        InputMangaCh = request.args.get('mangach')

        path = os.path.dirname(os.path.realpath(__file__))
        os.chdir(path)

        if os.path.exists('temp') == False:
            os.makedirs('temp')
        if os.path.exists('PDFs') == False:
            os.makedirs('PDFs')
        manga_search = get_search_results(query=InputMangaTitle)

        for k in manga_search:
            try:
                titleManga=(k.get('title' ))
            except AttributeError as attErr:
                print(f'{bcolors.FAIL}Query did not yield any results!{bcolors.ENDC}')
                quit()
        for k in manga_search:
            IdManga=(k.get('mangaid' ))

        mangaChNum= InputMangaCh
        # for k in manga_search:
        #     print(titleManga)

        manga_chapter = get_manga_chapter(mangaid=IdManga, chapNumber=mangaChNum)
        pdfName = titleManga+' ch.# '+ mangaChNum
        global FileName
        FileName = pdfName
        # print(manga_chapter)

        async def fetch(session, url):
            try:
                url = url[1:-1]
                async with session.get(url) as resp:
                    fileNameNE = (url.split('/')[-1]).split('.')[0]
                    fileName = fileNameNE+'.jpg'
                    fullFileName = 'temp/'+fileName
                    if resp.status == 200:
                        async with aiofiles.open(fullFileName, mode='wb') as f:
                            await f.write(await resp.read())
                            await f.close()
                        print(f'{bcolors.OKGREEN}Done: {bcolors.ENDC}{url}')
                        return fullFileName
                    else:
                        print(f'{bcolors.WARNING}Rejected URL: {url} | Status: {resp.status}{bcolors.ENDC}')
            except Exception as err:
                print(err)

        async def main(image_urls):
            tasks = []
            headers = Headers(headers=True).generate()
            async with aiohttp.ClientSession(headers=headers) as session:
                for image in image_urls:
                    coroutineTask = asyncio.ensure_future(fetch(session, image))
                    tasks.append(coroutineTask)
                data = await asyncio.gather(*tasks)
                return data
            
        def pdfGen(imageList):
            pdf = FPDF()
            for image in imageList:
                if image == None:
                    continue
                cover = Image.open(image)
                width, height = cover.size
                width, height = float(width * 0.264583), float(height * 0.264583)
                pdf_size = {'P': {'w': 210, 'h': 297}, 'L': {'w': 297, 'h': 210}}
                orientation = 'P' if width < height else 'L'
                width = width if width < pdf_size[orientation]['w'] else pdf_size[orientation]['w']
                height = height if height < pdf_size[orientation]['h'] else pdf_size[orientation]['h']

                pdf.add_page(orientation=orientation)

                pdf.image(image, 0, 0, width, height)
            
            pdf.output(f"PDFs/{pdfName}.pdf", "F")
            print(f'{bcolors.OKCYAN}Generated PDF: {pdfName}.pdf {bcolors.ENDC}')
            
        
        if __name__ == "__main__":
            try:
                image_urls = (manga_chapter['totalPages']).strip('][').split(', ')
                result = asyncio.run(main(image_urls))
                pdfGen(result)
                files = glob.glob('temp/*')
                for f in files:
                    os.remove(f)
                
            except Exception as e:
                print(e)
        return render_template("manga.html", pdfName = pdfName) 
        
    except IndexError:
        return render_template(
        "error.html")

@app.route('/return-files/')
def return_files_tut():
    try:
        return send_file(f'PDFs/{FileName}.pdf')
    except Exception as e:
        return str(e)
    
if __name__ == "__main__":
    app.run(debug=False, port=80)

as u can see its supposed to save pdf in PDFs/{pdfName}.pdf but when try to send file it says its not there

i tried changing file path and no luck.

Asked By: Samurai6465

||

Answers:

It won’t work if you just copy your script into a Flask application. Adjust your code to the circumstances and it will work.

You should be concerned with the line if __name__ == '__main__': . This makes no sense within your route. Read here to get more information.

The example below uses Flask’s async extra and should meet your needs.

The user can search for publications by entering a title. If he then selects one, the possible chapters are offered as a PDF for download. If a chapter is selected for download, the processing essentially corresponds to your specifications. A temporary directory is created into which the available images are downloaded. You have two alternatives to choose from, depending on where and how you want to create the directory. Once all images have been loaded, a PDF is generated based on their path information, which is delivered directly from memory. The directory used is then deleted.

Flask
from PIL import Image
from flask import (
    Flask, 
    abort, 
    render_template, 
    request, 
    send_file
)
from fpdf import FPDF
from functools import partial
from io import BytesIO
from kissmanga import (
    get_search_results, 
    get_manga_details, 
    get_manga_episode, 
    get_manga_chapter
)

import asyncio
import aiohttp
import aiofiles
import os
import shutil
import tempfile
import urllib
import uuid

app = Flask(__name__)

@app.route('/')
def index():
    title = request.args.get('qs')
    results = []
    if title:
        results = get_search_results(query=title)
        if 'status' in results:
            results = []
    return render_template('index.html', **locals())

@app.route('/episode/<mangaid>')
def episode(mangaid):
    try:
        episode = get_manga_episode(mangaid=mangaid)
        return render_template('episode.html', **locals())
    except Exception as exc:
        abort(404)

@app.route('/chapter/<mangaid>/<int:num>')
async def chapter(mangaid, num):
    chapter = get_manga_chapter(mangaid=mangaid, chapNumber=num)
    if chapter == 'Invalid Mangaid or chapter number':
        abort(404)

    # Either manage a folder manually ... 
    # try:
    #   urls = eval(chapter['totalPages'])
    #   dest = os.path.join(app.instance_path, 'downloads', str(uuid.uuid4()))
    #   try:
    #       os.makedirs(dest)
    #   except: pass
    #   filenames = await download_chapter(mangaid, num, urls, dest)
    #   buffer = BytesIO(gen_pdf(filenames).encode('latin-1'))
    #   return send_file(
    #       buffer, 
    #       mimetype='application/pdf', 
    #       download_name=f'{mangaid}_{num}'
    #   )
    # except Exception as exc:
    #   app.logger.exception(exc)
    #   abort(500)
    # finally:
    #   shutil.rmtree(dest)

    # ... or use a temporary folder.
    with tempfile.TemporaryDirectory() as dest:
        try:
            urls = eval(chapter['totalPages'])
            filenames = await download_chapter(mangaid, num, urls, dest)
            buffer = BytesIO(gen_pdf(filenames).encode('latin-1'))
        except Exception as exc:
            app.logger.exception(exc)
            abort(500)

        return send_file(
            buffer, 
            mimetype='application/pdf', 
            download_name=f'{mangaid}_{num}'
        )

async def download_chapter(mangaid, chapter, urls, dest):
    def _url2path(url, root, size):
        _path = urllib.parse.urlparse(url).path
        _path, _name = os.path.split(_path)
        _root, _ext = os.path.splitext(_name)
        return url, os.path.join(root, f"{_root.rjust(size, '0')}{_ext}")
    async with aiohttp.ClientSession() as session:
        size = len(str(len(urls)))
        tasks = [
            fetch(session, _url, _path) 
            for _url, _path in map(partial(_url2path, root=dest, size=size), urls)
        ]
        return await asyncio.gather(*tasks)

async def fetch(session, url, filename):
    try:
        async with session.get(url) as response:
            assert response.status == 200
            async with aiofiles.open(filename, mode='wb') as fp:
                await fp.write(await response.read())
            return filename
    except Exception as exc:
        return None

def gen_pdf(filenames):
    pdf = FPDF() 
    for filename in filenames:
        if not filename: continue
        cover = Image.open(filename)
        width, height = cover.size
        if width < height: 
            pdf.add_page(orientation='P')
            pdf.image(
                filename, 
                0, 0, 
                max(210, min(210, width)), 
                max(297, min(297, height))
            )
        else:
            pdf.add_page(orientation='L')
            pdf.image(
                filename, 
                0, 0, 
                max(297, min(297, width)), 
                max(210, min(210, height))
            )
    return pdf.output(dest='S')
HTML (./templates/index.html)
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Index</title>
</head>
<body>
    <form>
        <input type="text" name="qs" autocomplete="off" spellcheck="false" value="{{ title or '' }}" />
        <input type="submit" value="Go" />
    </form>

    <div>
        {% if results -%}
        <ul>
            {% for item in results -%}
            <li><a href="{{ url_for('episode', mangaid=item.mangaid) }}">{{ item.title }}</a></li>
            {% endfor -%}
        </ul>
        {% else -%}
        <p>No results found</p>
        {% endif -%}
    </div>
</body>
</html>
HTML (./templates/episode.html)
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Episode</title>
</head>
<body>
    <h1>{{ episode.title }}</h1>
    <ul>
    {% for i in range(1, episode.totalchapter | int + 1) -%}
    <li><a href="{{ url_for('chapter', mangaid=mangaid, num=i) }}">Chapter {{ i }}</a></li>
    {% endfor -%}
    </ul>
</body>
</html>
Answered By: Detlef
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.