如何在Python解码Dart readAsBytesSync()编码的图片字节及Flutter最优编解码方案
Great questions—let's walk through each one clearly, since I've built similar Flutter-Python image transfer pipelines before:
1. How readAsBytesSync() converts images to bytes
readAsBytesSync() is a synchronous method from Dart's dart:io File class, and it does exactly what it sounds like: it reads every single byte of the file from your storage exactly as it exists on disk.
For images, that means it grabs the raw binary data of the image file (like JPEG/PNG/GIF encoding, not decoded pixel values). It doesn't process or modify the image at all—just reads the sequence of bytes that make up the file and stores them in a List<int>. Think of it like copying the file's binary content directly into memory as a list of integers (each integer represents one byte, ranging from 0 to 255).
2. Restoring the bytes to an image in Python
When you use json.encode() on your {"img": imageBytes} map in Flutter, the JSON encoder converts the List<int> of bytes into an array of integers in the JSON string. To get the image back in Python, you just need to reverse that process:
- Parse the incoming JSON string to extract the list of integers.
- Convert that integer list into a Python
bytesobject (Python's native type for raw binary data). - Use an image library like Pillow to load and save the image from those bytes.
Here's a concrete example (install Pillow first with pip install pillow):
import json from PIL import Image import io # Replace this with the actual string you receive from the WebSocket received_json_str = ... # Step 1: Parse the JSON payload data = json.loads(received_json_str) image_int_list = data["img"] # Step 2: Convert integer list to raw bytes image_bytes = bytes(image_int_list) # Step 3: Load and save the image with Image.open(io.BytesIO(image_bytes)) as img: # Pillow automatically detects the image format (JPG/PNG/etc.) img.save("restored_image.jpg") # Use img.show() if you want to view the image immediately
Note: Ensure your Python WebSocket library handles full message reception (most popular libraries like websockets do this automatically for text frames).
3. The most appropriate way to encode/decode images in Flutter
Your current approach works, but sending raw byte lists as JSON arrays is inefficient—each byte becomes a string representation of an integer, which bloats the data size significantly. Here are two better options, depending on your needs:
Option 1: Base64 Encoding (Best for sending with metadata)
Base64 converts binary data into a compact ASCII string, making it ideal for embedding in JSON if you need to send extra data (like image names, types, or timestamps) alongside the image.
Flutter code:
import 'dart:convert'; import 'dart:io'; import 'package:web_socket_channel/io.dart'; void sendImageWithMetadata() async { File imageFile = File("/path/to/your/image.jpg"); List<int> imageBytes = imageFile.readAsBytesSync(); // Encode bytes to Base64 string String base64Image = base64.encode(imageBytes); // Package into JSON with additional metadata var payload = json.encode({ "img": base64Image, "filename": "vacation_photo.jpg", "image_type": "jpg" }); var channel = IOWebSocketChannel.connect("ws://34.73.158.146:5903"); channel.sink.add(payload); }
Python decoding code:
import json import base64 from PIL import Image import io received_json_str = ... data = json.loads(received_json_str) # Decode Base64 string back to bytes image_bytes = base64.b64decode(data["img"]) with Image.open(io.BytesIO(image_bytes)) as img: img.save(data["filename"])
Option 2: Send Raw Binary (Most Efficient)
If you only need to send the image (no extra metadata), skip JSON entirely and send raw binary data directly over WebSocket. This is the fastest method with zero extra encoding overhead.
Flutter code:
import 'dart:io'; import 'package:web_socket_channel/io.dart'; void sendRawImage() async { File imageFile = File("/path/to/your/image.jpg"); Uint8List imageBytes = imageFile.readAsBytesSync(); var channel = IOWebSocketChannel.connect("ws://34.73.158.146:5903"); // Send raw binary data directly channel.sink.add(imageBytes); }
Python reception code:
import asyncio import websockets from PIL import Image import io async def receiveRawImage(): async with websockets.connect("ws://34.73.158.146:5903") as websocket: # Receive raw bytes directly from the WebSocket image_bytes = await websocket.recv() with Image.open(io.BytesIO(image_bytes)) as img: img.save("received_image.jpg") asyncio.run(receiveRawImage())
Which to choose? Use Base64+JSON if you need to send additional data with the image. Use raw binary if you want maximum efficiency and only need to transfer the image itself.
内容的提问来源于stack exchange,提问作者Zain Abedien

