Skip to Content
Menu
This question has been flagged
1 Reply
951 Views

So my goal is to send via api the image or pdf i have on odoo somewhere else.


the problem is i don't find the path of the odoo image I want to move, so i looked for it in :

invoice = self.env['account.move'].search([('id', '=', invoice_id)], limit=1)

attachments = invoice.attachment_ids

Where i found : attachments.local_url 

with this i could do : 

"http://localhost:8069/"+attachments.local_url

and it downloads it on my navigator.

so i'm like "ok i can download it here so i could just request it via code"


so I made this function : 

def url_to_document(self, url_attachments):

        import os

        import re

        import requests

        from urllib.parse import urlparse

        import mimetypes


        folder_path = './invoice/temp/'

        os.makedirs(folder_path, exist_ok=True)


        parsed_url = urlparse(url_attachments)

        raw_filename = os.path.basename(parsed_url.path) or 'downloaded_file'

        raw_filename = re.sub(r'[<>:"/\\|?*=]', '_', raw_filename)


        try:

            response = requests.get(url_attachments, headers={

                        "User-Agent": (

                            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "

                            "AppleWebKit/537.36 (KHTML, like Gecko) "

                            "Chrome/114.0.0.0 Safari/537.36"

                        ),

                        "Accept": "application/pdf,application/octet-stream;q=0.9,*/*;q=0.8",

                        "Accept-Encoding": "identity",

                    })

            response.raise_for_status()


            content_type = response.headers.get("Content-Type", "").lower()

            extension = mimetypes.guess_extension(content_type.split(';')[0]) or '.bin'


            if content_type == 'application/pdf':

                extension = '.pdf'

            elif content_type == 'image/png':

                extension = '.png'

            elif content_type == 'image/jpeg':

                extension = '.jpg'


            filename = os.path.splitext(raw_filename)[0] + extension

            full_file_path = os.path.join(folder_path, filename)


            with open(full_file_path, 'wb') as f:

                f.write(response.content)


            print(f"✅ Saved as: {full_file_path}")

            return full_file_path


        except requests.RequestException as e:

            print(f"❌ Error downloading file: {e}")

            return None


The problem : 

  1. The function does request something but for some reason it gets a png enven thought on the web it's a pdf
  2. the png img is a default camera logo

solutions : ??

  1. Is there another solution you guys have to find the document
  2. am i missing something evident in my code or the way this "http://localhost:8069/"+attachments.local_url works ?


Thank you for the read,

have a nice day


Avatar
Discard
Best Answer

HIi,

Best option if you're writing Odoo module code (inside Odoo)

  • No need for HTTP requests
  • Fast and secure (reads directly from DB)
  • No login/session issues

Use when:

  • You're writing Python code inside Odoo (e.g., in a model or scheduled action)
  • You want to send the file somewhere else (via API, save to disk, etc.)


import base64

attachment = invoice.attachment_ids[0]

binary = base64.b64decode(attachment.datas)

with open(f"/tmp/{attachment.name}", "wb") as f:

    f.write(binary)


and other option is 
uthenticate the HTTP Request with Odoo Session Cookie

If you must use requests, first log in via /web/session/authenticate, then pass the auth cookie:
def get_odoo_session_cookie(base_url, db, username, password):

    import requests


    url = f"{base_url}/web/session/authenticate"

    payload = {

        "jsonrpc": "2.0",

        "params": {

            "db": db,

            "login": username,

            "password": password,

        }

    }

    session = requests.Session()

    response = session.post(url, json=payload)

    if response.status_code == 200 and response.json().get('result', {}).get('uid'):

        return session  # This session holds the auth cookies

    else:

        raise Exception("Authentication failed")

Then reuse that session:

session = get_odoo_session_cookie("http://localhost:8069", "your_db", "admin", "admin")


url = "http://localhost:8069" + attachments.local_url

response = session.get(url)


with open("file.pdf", "wb") as f:

    f.write(response.content)


Avatar
Discard
Related Posts Replies Views Activity
0
Aug 25
176
1
Aug 25
302
0
Aug 25
221
2
Aug 25
233
2
Aug 25
789