Можно ли отправить файловый объект в запросе из строки base64 без необходимости записывать его в файл, а затем читать из него?

#python

#python

Вопрос:

У меня есть этот метод python, который получает dict

 {
  "filename": "image.png",
  "data": <base64 string>
}
  

создает локальный файловый объект, записывает в него, а затем считывает из него и отправляет его в запросе.

Можно ли создать файловый объект и отправить его с запросом без необходимости записывать его локально?

Ниже приведен метод:

   def add_attachments(self, issue_key, data):
        # add attachment to issue
        try:
            attachments = data["attachments"]

            credentials = requests.auth.HTTPBasicAuth(settings.JIRA_USERNAME, settings.JIRA_TOKEN)
            headers = {'X-Atlassian-Token': 'no-check'}

            url = settings.JIRA_HOST   "/rest/api/2/issue/%s/attachments" % issue_key
            for attachment in attachments:
                print("Uploading file: "   attachment['filename'])
                filename = "temp/"   attachment['filename']
                # create a file in filepath if not exists
                if not os.path.exists(os.path.dirname(filename)):
                    try:
                        os.makedirs(os.path.dirname(filename))
                    except OSError as exc:  # Guard against race condition
                        if exc.errno != errno.EEXIST:
                            raise
                # write to file
                with open(filename, 'wb') as file:
                    data_bytes = attachment['data'].encode('utf-8')
                    decoded_data = base64.decodebytes(data_bytes)
                    file.write(decoded_data)
                    file.close()
                # read the file and send request to jira
                with open(filename, 'rb') as file:
                    r = requests.post(url, auth=credentials, files=[('file', file)], headers=headers)
                    file.close()

            shutil.rmtree("temp")
        except Exception as e:
            print(e)
            pass
  

Ответ №1:

Просто создайте файлоподобный объект в памяти, например:

 data_bytes = attachment['data'].encode('utf-8')
decoded_data = base64.decodebytes(data_bytes)
file = io.BytesIO(decoded_data)
r = requests.post(url, auth=credentials, files=[('file', file)], headers=headers)
  

Ответ №2:

Попробуйте использовать BytesIO следующим образом:

 file = io.BytesIO(base64.decodebytes(data_bytes))
  

Ответ №3:

Используйте BytesIO. Вы бы заменили эту часть:

 # write to file
with open(filename, 'wb') as file:
    data_bytes = attachment['data'].encode('utf-8')
    decoded_data = base64.decodebytes(data_bytes)
    file.write(decoded_data)
    file.close()
# read the file and send request to jira
with open(filename, 'rb') as file:
    r = requests.post(url, auth=credentials, files=[('file', file)], headers=headers)
    file.close()
  

с помощью этого:

 from io import BytesIO

data_bytes = attachment['data'].encode('utf-8')
decoded_data = base64.decodebytes(data_bytes)
file = BytesIO(decoded_data) # create ByteIO object and put the decoded data into it

r = requests.post(url, auth=credentials, files=[('file', file)], 
headers=headers)