I don't know where you've learnt how HTTP works but I'm pretty sure that you did not study the actual standard which you should do when implementing a protocol. Some notes about your implementation:
- Line ends should be
\r\nnot\n. This is true for both responses from the server as requests from the client. - You are assuming that the clients requests is never larger than 1024 bytes and that it can be read within a single
recv. But, requests can have arbitrary length and there is no guarantee that you get all within a singlerecv(TCP is a streaming protocol and not a message protocol). - While it is kind of ok to simply close the TCP connection after the body it would be better to include the length of the body in the
Content-lengthheader or use chunked transfer encoding. - The type of the content should be given by using the
Content-Typeheader, i.e.Content-type: text/htmlfor HTML andContent-type: image/jpegfor JPEG images. Without this browser might guess correctly or wrongly what the type might be or depending on the context might also insist on a proper content-type header.
Apart from that, if you debug such problems it is helpful to find out what gets actually exchanged between client and server. It might be that you've checked this for yourself but you did not include such information into your question. Your only error description is "...I recive the call but cannot preset the png/JPEG in the page" and then a dump of your code.
Answer from Steffen Ullrich on Stack OverflowI don't know where you've learnt how HTTP works but I'm pretty sure that you did not study the actual standard which you should do when implementing a protocol. Some notes about your implementation:
- Line ends should be
\r\nnot\n. This is true for both responses from the server as requests from the client. - You are assuming that the clients requests is never larger than 1024 bytes and that it can be read within a single
recv. But, requests can have arbitrary length and there is no guarantee that you get all within a singlerecv(TCP is a streaming protocol and not a message protocol). - While it is kind of ok to simply close the TCP connection after the body it would be better to include the length of the body in the
Content-lengthheader or use chunked transfer encoding. - The type of the content should be given by using the
Content-Typeheader, i.e.Content-type: text/htmlfor HTML andContent-type: image/jpegfor JPEG images. Without this browser might guess correctly or wrongly what the type might be or depending on the context might also insist on a proper content-type header.
Apart from that, if you debug such problems it is helpful to find out what gets actually exchanged between client and server. It might be that you've checked this for yourself but you did not include such information into your question. Your only error description is "...I recive the call but cannot preset the png/JPEG in the page" and then a dump of your code.
httpServer.py
Ended up like:
while True:
# Wait for client connections
client_connection, client_address = server_socket.accept()
# Handle client request
request = client_connection.recv(10240).decode()
content = handle_request(request)
# Send HTTP response
if content:
if str(content).find("html") > 0:
client_connection.send('HTTP/1.1 200 OK\n\n'.encode())
client_connection.send(content.encode())
else:
client_connection.send('HTTP/1.1 200 OK\r\n'.encode())
client_connection.send("Content-Type: image/jpeg\r\n".encode())
client_connection.send("Accept-Ranges: bytes\r\n\r\n".encode())
client_connection.send(content)
else:
response = 'HTTP/1.1 404 NOT FOUND\r\nFile Not Found'
client_connection.close()
And the Get method like:
class HTTPHandler:
def get(self, args, type):
if args == '/':
args = '/index.html'
fin = open('htdocs' + args)
if type != "image":
fin = open('htdocs/' + args)
if type.find("html") == -1:
image_data = open('htdocs/' + args, 'rb')
bytes = image_data.read()
# Content-Type: image/jpeg, image/png \n\n
content = bytes
fin.close()
return content
# Read file contents
content = fin.read()
fin.close()
return content
How to receive images on a python server from a client.
How to encode image to send over Python HTTP server? - Stack Overflow
How to send image using socketserver
How do I send image with Python requests and receive it with Flask request ?
Videos
Adding this reply if anyone needs it for future.
Please find the below code for sending image file in Python requests. Here logo is the keyword for an image file, which one of our servers accepts as an input. Hence 'logo' is given. Also, make sure you remove 'Content-type' from the headers.
response = requests.post(url,data=data,headers=headers, files={'logo':open("your_image_file.jpeg",'rb')})
I have found the solution, it is quite easy:
data = {'upload': ''}
I needed to pass the upload string in that way and voilà!
I'm trying to receive images on my python program, I've searched a lot on the internet but most of them are just tutorials about sending images. I found a few about receiving but none of them worked for me. All the other ones with receiving did it using a GET request first, which is not what I want. I'm sending a cURL POST request with a file in it (later on it will be sent from a real server, not a cURL) I want the server to keep listening until I upload/POST an image, then I want to receive the image and display it using PIL.
Here is the code I found online but doesn't work, I really have no clue how to receive images.
import socket
import struct
from PIL import Image
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 12801))
s.listen(1000)
print('Waiting for data...')
client, addr = s.accept()
print('got connected from', addr)
buf = b'' # this caused an error, I added a b so it would be read as bytes and not string
while len(buf)<4:
buf += client.recv(4-len(buf))
size = struct.unpack('!i', buf)
print("receiving %s bytes" % size)
with open('tst.jpg', 'wb') as img:
while True:
data = client.recv(1024)
if not data:
break
img.write(data)
print('received image')Here is the output when I send a 101.345 bytes JPG file
Waiting for data...
got connected from ('127.0.0.1', 51861)
receiving 1347375956 bytes1347375956 bytes... that's clearly bugged and not working properly. It's also stuck at that part just waiting.
Just to show you how I got the sending part working and how easy that was (it's not sending to a python program/server, but to an ESP webserver)..:
url = ' http://192.168.x.xx/fupload'
files = {'media': open('converted_image.bmp', 'rb')}
req.post(url, files=files)I hope anyone can help me out.
For a PNG image you have to set the content-type to "image/png". For jpg: "image/jpeg".
Other Content types can be found here.
Edit: Yes, I forgot about encoding in my first edit.
The answer is: You don't! When you load your image from a file, it is in the correct encoding already.
I read about your codec problem: The problem is, as much I see in your load function. Don't try to encode the file content.
You may use for binary data this:
def load_binary(filename):
with open(filename, 'rb') as file_handle:
return file_handle.read()
As mentioned by Juergen you have to set the accordingly content-type. This example I found may help you: https://github.com/tanzilli/playground/blob/master/python/httpserver/example2.py
The example is in Python 2, but the changes should be minor.
Ah and it's better to use self instead of client -> see PEP 8, Python's style guide
Hi Flaskers,
I'm having difficulty receiving image on the Flask backend:
@auth_blueprint.route('/auth/check_image', methods=['POST'])
@cross_origin()
def check_image():
try:
image_given = request.files['photo'] # <-- image won't make it to Flask
img = Image.open(image_given.stream)
return jsonify({'status': 'OK', 'message': f'{img.width} {img.height}'})Kivy front-end:
img = {'file': ('photo': open(f'{self.image_path}/example.jpg', 'rb'))}
try:
response = requests.post('http://www.example.com/auth/check_image', files=img)
print(str(response.content, 'utf-8'))Error output:
<title>500 Internal Server Error</title> 03-02 17:06:26.295 15175 15678 I python : <h1>Internal Server Error</h1> 03-02 17:06:26.295 15175 15678 I python : <p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
Error output from the backend:
"content":"400 Bad Request: The browser (or proxy) sent a request that this server could not understand.","status":"fail"
I've found this block of code that allegedly works:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/im_size", methods=["POST"])
def process_image():
file = request.files['image']
# Read the image via file.stream
img = Image.open(file.stream)
return jsonify({'msg': 'success', 'size': [img.width, img.height]})
if __name__ == "__main__":
app.run(debug=True)url = 'http://127.0.0.1:5000/im_size'
my_img = {'image': open('test.jpg', 'rb')}
r = requests.post(url, files=my_img)
# convert server response into JSON format.
print(r.json())I found the code here https://jdhao.github.io/2020/04/12/build_webapi_with_flask_s2/, strangely I'm getting status code 400 using it.
Thank you for any insight.
From wechat api doc:
curl -F [email protected] "http://file.api.wechat.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"
Translate the command above to python:
import requests
url = 'http://file.api.wechat.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE'
files = {'media': open('test.jpg', 'rb')}
requests.post(url, files=files)
Doc: https://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file
In case if you were to pass the image as part of JSON along with other attributes, you can use the below snippet.
client.py
import base64
import json
import requests
api = 'http://localhost:8080/test'
image_file = 'sample_image.png'
with open(image_file, "rb") as f:
im_bytes = f.read()
im_b64 = base64.b64encode(im_bytes).decode("utf8")
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
payload = json.dumps({"image": im_b64, "other_key": "value"})
response = requests.post(api, data=payload, headers=headers)
try:
data = response.json()
print(data)
except requests.exceptions.RequestException:
print(response.text)
server.py
import io
import json
import base64
import logging
import numpy as np
from PIL import Image
from flask import Flask, request, jsonify, abort
app = Flask(__name__)
app.logger.setLevel(logging.DEBUG)
@app.route("/test", methods=['POST'])
def test_method():
# print(request.json)
if not request.json or 'image' not in request.json:
abort(400)
# get the base64 encoded string
im_b64 = request.json['image']
# convert it into bytes
img_bytes = base64.b64decode(im_b64.encode('utf-8'))
# convert bytes data to PIL Image object
img = Image.open(io.BytesIO(img_bytes))
# PIL image object to numpy array
img_arr = np.asarray(img)
print('img shape', img_arr.shape)
# process your img_arr here
# access other keys of json
# print(request.json['other_key'])
result_dict = {'output': 'output_key'}
return result_dict
def run_server_api():
app.run(host='0.0.0.0', port=8080)
if __name__ == "__main__":
run_server_api()