2

I am trying to send image through API in Micropython. still no solution how to do it. please help

import urequests
import json
URL = 'https://example.com/test'
datas = json.dumps({"auth_key": "43435", "mac": "abcd", "name": "washid"})
filep = 'OBJ.jpg'
filess = {'odimg': open(filep, 'rb')}
try:
    response = urequests.post(URL,data=datas,files=files)
    print(response.json())
except Exception as e:
    print(e)

2 Answers2

1

Maybe this template can help you :

import ubinascii
import uos
import urequests


def make_request(data, image=None):
    boundary = ubinascii.hexlify(uos.urandom(16)).decode('ascii')

    def encode_field(field_name):
        return (
            b'--%s' % boundary,
            b'Content-Disposition: form-data; name="%s"' % field_name,
            b'', 
            b'%s'% data[field_name]
        )

    def encode_file(field_name):
        filename = 'latest.jpeg'
        return (
            b'--%s' % boundary,
            b'Content-Disposition: form-data; name="%s"; filename="%s"' % (
                field_name, filename),
            b'', 
            image
        )

    lines = []
    for name in data:
        lines.extend(encode_field(name))
    if image:
        lines.extend(encode_file('file'))
    lines.extend((b'--%s--' % boundary, b''))
    body = b'\r\n'.join(lines)

    headers = {
        'content-type': 'multipart/form-data; boundary=' + boundary,
        'content-length': str(len(body))}
    return body, headers


def upload_image(url, headers, data):
    http_response = urequests.post(
        url,
        headers=headers,
        data=data
    )
    if http_response.status_code == 204:
        print('Uploaded request')
    else:
        raise UploadError(http_response)
    http_response.close()
    return http_response

You need to declare an header for your request

Jonathan Delean
  • 1,011
  • 1
  • 8
  • 25
  • thanks for the reply jonathan, I am new in micropython, can you tell me the step , means should i call make-request() and passed image inside upload-image – Md Washid Husain Jun 17 '20 at 11:02
  • How should this be called, Jonathan? Do I prepare body and headers by running make_request, then feed them into upload_image (in a slightly different order)? – penitent_tangent Apr 15 '22 at 13:10
0

I used Jonathan's answer. Had to modify the code a bit (-thanks to Akshay to figure this out). A fixed boundary is used instead of generating a new one every time. Also, there needs to be an additional \r\n at the end of the file. I have used this to upload photos to Telegram Bot using ESP-32 CAM.

    def make_request(data, image=None):
        boundary = '---011000010111000001101001' 
        #boundary fixed instead of generating new one everytime

        def encode_field(field_name): # prepares lines that include chat_id
            return (
                b'--%s' % boundary,
                b'Content-Disposition: form-data; name="%s"' % field_name,
                b'', 
                b'%s'% data[field_name] #field_name conatains chat_id
            )


        def encode_file(field_name):  # prepares lines for the file
            filename = 'latest.jpg'  # dummy name is assigned to uploaded file
            return (
                b'--%s' % boundary,
                b'Content-Disposition: form-data; name="%s"; filename="%s"' % (
                    field_name, filename),
                b'', 
                image
            )

        lines = [] # empty array initiated
        for name in data:
            lines.extend(encode_field(name)) # adding lines (data)
        if image:
            lines.extend(encode_file('photo')) # adding lines  image
        lines.extend((b'--%s--' % boundary, b'')) # ending  with boundary

        body = b'\r\n'.join(lines) # joining all lines constitues body
        body = body + b'\r\n' # extra addtion at the end of file

        headers = {
            'content-type': 'multipart/form-data; boundary=' + boundary
            }  # removed content length parameter
        return body, headers  # body contains the assembled upload package


    def upload_image(url, headers, data):  
        http_response = urequests.post(
            url,
            headers=headers,
            data=data
        )
        print(http_response.status_code) # response status code is the output for request made
        
        if (http_response.status_code == 204 or http_response.status_code == 200):
            print('Uploaded request')
        else:
            print('cant upload')
            #raise UploadError(http_response) line commneted out
        http_response.close()
        return http_response  


    # funtion below is used to set up the file / photo to upload
    def send_my_photo(photo_pathstring): #  path and filename combined
        token = 'authentication token or other data' # this my bot token
        chat_id= 999999999 # my chat_id
        url = 'https://api.telegram.org/bot' + token
        path = photo_pathstring   # this is the local path
        myphoto = open(path , 'rb') #myphoto is the photo to send
        myphoto_data = myphoto.read() # generate file in bytes
        data = { 'chat_id' : 999999999 }
        body, headers  = make_request(data, myphoto_data) # generate body to upload 
        url = url + '/sendPhoto'
        headers = { 'content-type': "multipart/form-data; boundary=---011000010111000001101001" }
        upload_image(url, headers, body) # using function to upload to telegram