0

I have a problem while trying to upload files to discord. If I get it right, algorithm of uploading files to discord is next: I am sending information about the file that i want to upload, discord sending me link where i must put the file, i am put the file to the address given.

I have this code:

def Upload(link, channel, token):
  api_url = 'https://discord.com/api/v9/channels/'+channel+'/attachments'
  file_name = link[-10:]
  file_id = 1
  response = requests.get(link)
  open(file_name, "wb").write(response.content)
  file_size = os.path.getsize(file_name)
  upload = {"files":[{"filename":file_name,"file_size":file_size,"id":file_id}]}
  file = open(file_name, 'rb')
  header = {'authorization' : token}
  response = requests.post(api_url, headers=header, json=upload)
  put_url = response.json()['attachments'][0]['upload_url']
  put_name = response.json()['attachments'][0]['upload_filename']
  put_headers = {'Content-Length': str(file_size), 'Connection': 'keep-alive', 'Content-Type': 'image/png', 'authorization' : token}
  response = requests.put(put_url, headers=put_headers, data=file)
  return response

As first sight everything seems to be working. Response code is 200, everything ok.

But if I try to get headers - print(response.headers), I've got next message:

{'X-GUploader-UploadID': 'bla-bla-bla', 'ETag': '"bla-bla"', 'x-goog-generation': '1682338706931190', 'x-goog-metageneration': '1', 'x-goog-hash': 'bla-bla-bla', 'x-goog-stored-content-length': '1112324', 'x-goog-stored-content-encoding': 'identity', 'Vary': 'Origin', 'Content-Length': '0', 'Date': 'Mon, 24 Apr 2023 12:18:26 GMT', 'Server': 'UploadServer', 'Content-Type': 'text/html; charset=UTF-8'}

I've got:

'Content-Length' = '0', 'Content-Type' = 'text/html; charset=UTF-8'.

And changing the "put_headers" does not affect it, absolutely. I've sent 1112324 bytes, wtf? I see the 'x-goog-stored-content-length' = '1112324',

but I don't know what's going wrong.

In addition, if I'm trying to use the "uploaded" attachment in next message - I'm receiving error (wrong attachment).

What I'm doing wrong?

I tried to use POST, but discord does not accept this method for attachments.

2 Answers 2

1

The response is as expected – the response's content length is zero (since there's nothing to say – "200 OK" to tell you it was fine and the metadata in the header is enough).

I think you'll find the actual read URL for the attachment in that response.json()['attachments'] list.

To clean your code up a bit (e.g. using a temporary file so it gets automagically cleaned up, and calling raise_for_status() so you get exceptions when they arise), you might want

import tempfile

import requests


def Upload(link, channel, token):
    file_name = link[-10:]
    data_response = requests.get(link)
    data_response.raise_for_status()
    with tempfile.TemporaryFile("w+b") as file:
        # Write the data to a temporary file
        file.write(data_response.content)
        file.flush()
        file_size = file.tell()
        # Seek back to the start
        file.seek(0)
        api_response = requests.post(
            f"https://discord.com/api/v9/channels/{channel}/attachments",
            headers={"authorization": token},
            json={"files": [{"filename": file_name, "file_size": file_size, "id": 1}]},
        )
        api_response.raise_for_status()
        attachment_info = api_response.json()["attachments"][0]
        put_url = attachment_info["upload_url"]
        put_response = requests.put(
            put_url,
            headers={
                "Content-Length": str(file_size),
                "Content-Type": "image/png",
                "authorization": token,
            },
            data=file,
        )
        put_response.raise_for_status()
    return attachment_info

(You also could just use an io.BytesIO() to not touch the disk at all, since you're not streaming the original response in the first place.)

Sign up to request clarification or add additional context in comments.

4 Comments

Seems like, there is no json response, because if i trying to get print(response.json()), he writes the next error: requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
You're overwriting response three times in your original code, mind.
If Im trying to use attachment in the next message (usually its using attachment parameters that i described on first step) - "attachments":[{"id":file_id,"filename":file_name,"uploaded_filename":put_name}] - it throws error "wrong attachment"
INTERACTION_APPLICATION_COMMAND_OPTIONS_INVALID_ATTACHMENT - discord answer when Im trying to use attachment
0

The problem was in the row 'file_id = 1' I tried to change it to 'file_id = 0' and all started to work! @AKX thank you for help and for very good advice about tempfile and raise_for_status. Its very useful!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.