Troubleshooting 'File Not Found' Error in FastAPI & Aiogram Bot When Accessing Files via Ngrok

31 Views Asked by At

I'm developing an aiogram bot that uses an API for image generation. Here's the workflow: a user uploads an image, the bot sends it through the API, and then the result is received via a webhook. I'm using ngrok for testing.

Everything functions well except for when the bot is supposed to find the image returned via the webhook but fails to do so. I've tried all possible solutions, but to no avail. Attempting to create another URL using the GET method with a 'get_image' handler, which should retrieve the photo, results in an error stating the script does not exist. I'm uncertain about the correct way to save the photo.

I want to avoid the method of saving photos in memory and then transferring them to the user as it takes up too much space. The main issue is that the bot cannot find the photo where it supposedly doesn't exist. I'm confident there are no errors from the API's side; the issue seems to be with how I'm saving the photos.

fastapi_server.py:

import os

from aiohttp.web_fileresponse import FileResponse
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
import logging
import aiofiles

app = FastAPI()
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)


@app.post("/webhook/")
async def handle_webhook(status: str = Form(...), id_gen: str = Form(...), time_gen: str = Form(...),
                         file: UploadFile = File(None)):
    # Create 'photos' directory if it doesn't exist
    os.makedirs('photos', exist_ok=True)

    logger.debug(f"Webhook called with id_gen: {id_gen}, status: {status}, time_gen: {time_gen}")
    if file and status == '200':
        try:
            # Save file content
            file_content = await file.read()
            file_path = f"photos/{id_gen}.jpg"
            async with aiofiles.open(file_path, "wb") as out_file:
                await out_file.write(file_content)
            logger.debug(f"Image saved for id_gen: {id_gen} at {file_path}")
            return {"status": "Image saved", "path": file_path}
        except Exception as e:
            logger.exception(f"Error saving image: {e}")
            return {"error": "Error saving image"}, 500
    else:
        logger.error(f"Error in webhook operation: {status}")
        return {"error": "Webhook error"}, 500

@app.get("/get_file/{file_id}")
async def get_file(file_id: str):
    file_path = f"{file_id}.jpg"
    if os.path.exists(file_path):
        return FileResponse(file_path)
    else:
        raise HTTPException(status_code=404, detail="File not found")


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

bot.py(this is where the bot should extract photos from the webhook)

@router.message(F.photo)
async def handle_photo(message: types.Message):
    user_id = message.from_user.id
    logger.debug(f" User ID: {user_id}")
    photo = message.photo[-1]  # Taking the largest size image
    logger.debug(f"️ Photo info: {photo}")
    file_info = await bot.get_file(photo.file_id)
    logger.debug(f" File info: {file_info}")

    photo_bytes_io = await bot.download_file(file_info.file_path)
    photo_bytes = photo_bytes_io.getvalue()  # Converting BytesIO to bytes
    logger.debug(f" Photo size in bytes: {len(photo_bytes)}")
    if not photo_bytes:
        logger.error(" The photo file is empty!")
        await message.answer("An error occurred while processing the photo.")
        return

    logger.debug(" Sending photo to Clothoff server...")
    await send_photo_to_clothoff(user_id, photo_bytes)
    await message.answer("Photo sent for processing. Please wait.")
    logger.debug(" Photo sent.")
dp.include_router(router)

async def fetch_and_send_photo(user_id, gen_id):
    file_url = f"https://a8e1-213-211-90-246.ngrok-free.app/get_file/{gen_id}"
    async with aiohttp.ClientSession() as session:
        async with session.get(file_url) as response:
            if response.status == 200:
                photo_data = await response.read()
                await bot.send_photo(user_id, photo=photo_data)
            else:
                print(f"Error: Unable to fetch file {gen_id}.jpg")

async def check_and_send_photo():
    while True:
        await asyncio.sleep(5)
        for user_id, gen_id in list(user_to_gen_map.items()):
            try:
                await fetch_and_send_photo(user_id, gen_id)
                logger.debug(f"Photo {gen_id}.jpg successfully sent to user {user_id}")
            except Exception as e:
                logger.error(f"Error sending photo to user {user_id}: {e}")
            finally:
                del user_to_gen_map[user_id]  # Removing the entry from the dictionary after attempting to send

I tried to send photos directly from fastapi, but the logs do not give an error, and the photo is not sent to the user.

0

There are 0 best solutions below