Search code examples
pythonhttpsimplehttpserver

How to read image from python http.server POST requests without downloading


I'm new to python and http.server, I'm doing a simple API which allow client to post an image and server can do something with that image.

Below is my do_POST method:

class Server(BaseHTTPRequestHandler):
    def do_POST(self):
        self.path = '/upload'
        content_length = int(self.headers['Content-Length'])
        file_content = self.rfile.read(content_length)
        #do something with the image here

        #response
        response = f'Message:'
        self.send_response(200) #create header
        self.send_header("Content-Length", str(len(response)))
        self.end_headers()

and my requests:

r = requests.post('http://127.0.0.1:8000/upload', files = {'image': open('C:/Users/Hp/IMG20220315112838.jpg','rb')})

However, the file_content also contains metadata of image and other informations like that: b'--ecd5d189dbf1c44dd325bf7134f386eb\r\nContent-Disposition: form-data; name="image"; filename="IMG20220315112838.jpg"\r\n\r\n\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xe1\x02\xe8Exif\x00\x00II*\x00\x08\x00\x00\x00\x0b\x00\x00\x01\x03\x00\x01\x00\x00\x00@\x07\x00\x00\x01\x01\x03\x00\x01\x00\x00\x00\xc0\x0f\x00\x00\x0f\x01\x02\x00\x05\x00\x00\x00\xa2\x00\x00\x00\x10\x01\x02\x00\r\x00\x00\x00\xa8\x00\x00\x00\x12\x01\x03\x00\x01\x00\x00\x00\x0

My question is how to get the bytes of only image to use with something like cv2.imshow() ? And another small question is how to handle with multiple images upload such as

r = requests.post('http://127.0.0.1:8000/upload', files = {
'image1': open('C:/Users/Hp/IMG20220315112838.jpg','rb'), 
'image2': open('C:/Users/Hp/IMG123456789.jpg','rb'), })

Thank you very much for helping out. Edit1: I tried file_content.decode('UTF-8') but it print out error: 'utf-8' codec can't decode byte 0xff in position 118 Position 118 is exactly after the filename string.


Solution

  • Im answering my own question: I tried requests-toolbelt parser to get the data as below:

    from requests_toolbelt.multipart import decoder
    class Server(BaseHTTPRequestHandler):
        def do_POST(self):
            self.path = '/upload'
            content_length = int(self.headers['Content-Length'])
    
            #get data content bytes
            file_content = self.rfile.read(content_length)
    
            #Use multipart parser to strip boundary
            multipart_data = decoder.MultipartDecoder(file_content, self.headers['Content-Type']).parts
            image_byte = multipart_data[0].content
            #Read image using cv2
            image_numpy = np.frombuffer(image_byte, np.int8)
            img = cv2.imdecode(image_numpy, cv2.IMREAD_UNCHANGED)
    
            #Send response
            response = bytes('Message: Successesesese', 'utf-8')
            self.send_response(200) #create header
            self.send_header("Content-Length", str(len(response)))
            self.end_headers()
            self.wfile.write(response)