Android客户端,将我们的通用的bitmap转为jpg字节数组:
static byte[] compress(final Bitmap bitmap) {
if(bitmap == null){
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, QUALILY, out);
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
然后,我们通过Base64.encodeToString将这个数据加密成一个字符串,就可以当作json的一项作为jsonstring发送给服务端。
Python服务端,解密然后保存到jpg文件即可:
而下载文件更简单,使用PIL.Image,可以读出imagedata,然后写到BytesIO中即可。
服务端的读写代码如下:
from abc import ABC
from tornado.web import RequestHandler
from libs.hooks import check_token
from libs.encode import Encode
import time
import io
from PIL import Image
from settings.config import max_img_size
class ImageHandler(RequestHandler, ABC):
async def get(self, *args, **kwargs):
url = self.request.uri
if url.startswith("/image/") and url.endswith(".jpg"):
file_name = 'static/upload/{}'.format(url[7:])
await self.download(file_name)
pass
else:
self.write("Invalid path ")
self.write_error(404)
@check_token
async def post(self):
url = self.request.uri
token = self.get_body_argument('token')
if url.startswith("/image/upload"):
image = self.get_body_argument('image')
image_data = Encode.decode(image)
ut = int(time.time())
file_name = token + str(ut) + ".jpg"
save_to = 'static/upload/{}'.format(file_name)
await self.upload(image_data, save_to)
self.write_error(404)
async def download(self, file_name):
try:
img = Image.open(file_name)
height = img.size[1]
width = img.size[0]
while (height > max_img_size) or (width > max_img_size):
height = height//2
width = width//2
print(width, height)
img = img.resize((width, height))
except FileNotFoundError:
self.write_error(404)
return
bio = io.BytesIO()
img.save(bio, "PNG")
self.set_header('Content-Type', 'image/PNG')
self.write(bio.getvalue())
pass
@staticmethod
async def upload(image_data, save_to):
with open(save_to, 'wb') as f:
f.write(image_data)
路由
(r'/image/(.*)', ImageHandler),
2020年4月9日,补充更简单的图片下载方式:
1)参考StaticFileHandler的get方法:
async def download(self, file_name):
try:
pic = open(file_name, "rb")
except FileNotFoundError:
self.write_error(404)
return
self.write(pic.read())
self.set_header('Content-Type', 'image/png')
pass
注意要以rb方式打开。
2)设置静态文件路径:
(r'/image/(.*)', StaticFileHandler,
{"path": os.path.join(os.path.dirname(__file__), "../static/upload"), "default_filename": "default.jpg"}),
第二中方法的缺点是谁都可以下载,没法check。