skip to Main Content
@dp.message_handler(content_types=types.ContentType.DOCUMENT)
async def scan_message(file: types.File):
    print("downloading document")
    file_path = file.file_path
    destination = r"C:usersaleksPycharmProjectspythonProjectfile.pdf"
    destination_file = bot.download_file(file_path, destination)
    print("success")

I would like to be able to download a file (in this case it is pdf) that was sent to my bot by the user. But the problem is that the bot doesn’t even recognize a file (when I send a file, it doesn’t even print "downloading document")

2

Answers


  1. You did not specify version of aiogram. I guess it is 2.x.

    All asynchronous function registered, as message handler must take the first positional parameter received message. If you like type hints you must to specify your function as

    async def scan_message(message: types.Message):
    

    for download your document you need just:

    destination_file = await message.document.download(destination)
    

    so correct handler for download document is:

    async def scan_message(message: types.Message):
        print("downloading document")
        destination = r"C:usersaleksPycharmProjectspythonProjectfile.pdf"
        destination_file = await message.document.download(destination)
        print("success")
    
    Login or Signup to reply.
  2. TL;DR

    I hope you’re using aiogram v2.x.

    Make sure that’s the only handler for types.ContentType.DOCUMENT without filters and your bot can get needed updates, then:

    @dp.message_handler(content_types=types.ContentType.DOCUMENT)
    async def scan_message(message: types.Message):
        print("downloading document")
        destination = r"C:usersaleksPycharmProjectspythonProjectfile.pdf"
        await message.document.download(destination)
        print("success")
    

    Detailed

    Everything described below applies to stable aiogram v2.x.

    1. aiogram.Dispatcher class parses raw telegram Update and sends it parsed and unpacked to corresponding handler, e.g. dp.message_handler will receive aiogram.types.Message for updates containing message, dp.callback_query_handler will receive aiogram.types.CallbackQuery for updates containing callback_query and so on. In your case you are expecting aiogram.types.File, which is wrong. Then dispatcher checks filters and calls corresponding handlers in registration order and stops dispatching if any handler was called.

      Consider the following example:

      # Some code omitted in favor of brievity
      @dp.message_handler()
      async def handle1(msg: types.Message):
          print("handled 1")
      
      @dp.message_handler()
      async def handle2(msg: types.Message):
          print("handled 2")
      

      You send any text message then look at bot’s console. There will only "handled 1" be printed because it was the first matching handler and only one handler is called.

    2. Bots have so-called "Privacy mode" in group chats, so not every message comes to your bot in a group. This is not the case in private (direct) messages, so it’s better to test your bot in private. You can read more about Privacy mode in official Bot API docs: https://core.telegram.org/bots#privacy-mode.

    3. It’s better and more readable to use shortcuts which are contained in each class, e.g. you can .reply() or .answer() to a aiogram.types.Message, which is a shortcut for aiogram.Bot.send_message(). Same with downloading file, you can just use .download() on aiogram.types.Document, aiogram.types.PhotoSize and so on. You can find more downloadable types by looking for classes that implement aiogram.types.mixins.Downloadable.

    4. All .download() methods return destination where the file was saved. If you pass your own optional destination as the first argument to the method, it’ll be useless to get it back as you already know it.

    So, after these modifications, you’ll get the code as in TL;DR section.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search