纯JS实作照片上传、下载与预览

更多会员限定文章可以到patreon观看


完整code可以到以下gist

Client端HTML

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    <style>        img {            width: 150px;          }    </style></head><body>    <input type="file" id="file-uploader" accept="image/png" multiple="multiple"/>    <img id='preview'> </body></html>
input tagtype设成file,让使用者能选择档案accept设定使用者能选的格式,如果要所有照片格式就改成image/*multiple让使用者能选择多个档案

Client端JS

我们会用JSON来传递资料(也可以用form-data)

取得使用者选择的照片

读进来的每个档案会是blob(Binary Large Object)

const fileUploader = document.querySelector('#file-uploader');fileUploader.addEventListener('change', (e) => {   console.log(e.target.files); // get list of file objects});

e.target.files是fileList

将照片转成base64 string

function display_img(curFiles) {    const curFile = curFiles[0];    const reader = new FileReader();    // 这会在readAS后才执行    reader.onload = function (e) {        // console.log('file:', e.target.result); // base64        document.querySelector('#preview').src = e.target.result;    };    // to data url    reader.readAsDataURL(curFile);}

img.src能显示url with base64

将blob转成array buffer

相较于buffer, blob保留了照片的资讯,像是档名、MIME type等

function blob2buffer(blob) {    return new Promise((resolve, reject) => {        var arrayBuffer;        var fileReader = new FileReader();        fileReader.onload = function (event) {            arrayBuffer = event.target.result;            resolve(arrayBuffer);        };        fileReader.readAsArrayBuffer(blob);        return arrayBuffer;    });}

先将blob转成buffer,方便后续建成array

将array转成字串post到server

buffer不能直接操作,要先转成指定type的array

arrayBuffer = await blob2buffer(pic);fetch(url, {    method: 'POST',    // flask need to set header of json    headers: {        'content-type': 'application/json'    },    body: JSON.stringify({        item_id: 1,        format: 'png',        img: Array.from(new Uint8Array(arrayBuffer)),    }),})

转成array前要先将buffer转成typed array

读取server端传回来的array

产生blob的url (不同于前面产base64的fileReader)

function display_arr_img(arr) {    document.querySelector('#preview').src = URL.createObjectURL(new Blob([new Uint8Array(arr)], {type: "image/png"}));}

将array转回typed array,再将其变回blob


Server端API

这里我们用python + flask作为例子

DataBase

这里我们用MySQL,然后照片的栏位type是blob,要注意blob有分可以存的size

TINYBLOB: maximum length of 255 bytesBLOB: maximum length of 65,535 bytes => 64kbMEDIUMBLOB: maximum length of 16,777,215 bytesLONGBLOB: maximum length of 4,294,967,295 bytes

连接到资料库

import pymysqlconnection = pymysql.connect(host='localhost', user='root', password='password', db='db01', charset='', cursorclass=pymysql.cursors.DictCursor)

注意pymysql不支援connection string

Python Code

所需套件在requirements.txt内

存到blob的好处是不会让照片被额外index (会导致档案大小增幅30%)

@app.route('/upload/json/img_raw', methods=['POST'])def raw_img():    json_data = flask.request.json    # save to db    with connection.cursor() as cursor:        sql = "UPDATE table1 SET `img_raw`=%s WHERE id=%s"        try:            # img现在是list, 可以用json string/ byterarray/ base64存进资料库            cursor.execute(sql, (json.dumps(json_data['img']), json_data['item_id']))            connection.commit()        except Exception as err:            connection.rollback()            return flask.jsonify({'err': err})        # get a picture        sql = "SELECT * FROM table1"        cursor.execute(sql)        result = cursor.fetchone()        r = result[0]['img_raw']        r = json.loads(r.decode())  # utf-8, 也可用ascii            return flask.jsonify({'img': r})

存进mysql blob栏位后,会变成binary object

json.dumps(json_data['img']我们要将List转成json style的string才能存进资料库json.loads(r.decode())存资料库拿出来的会是binary object,我们要先将其转回字串然后再将字串 parse回list

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章