从头完成一个restful API 服务

网友投稿 230 2023-05-22

上次我们一起完成了一个初级的API服务器的搭建,今天来给它增加点新功能,要看前面内容的,​​戳这里​​

1.完善设计

在上次的设计当中,我们定义了三张表,AdminUser,用来作为调用 API 鉴权用户,User,用来作为存储普通用户使用,Picture,用来作为存储用户上传的图片。但是当时只是实现了 AdminUser 的相关功能,而 User 和 Picture 还没有真正的关联起来,这次就把它们完善起来

2.测试 server

为了方便测试,我们这里写了一个简单的测试 web server,用来在网页上向 API 服务器发请求。代码很简单,还是用 flask 来启动 server,返回一个页面。

复制@app.route(/jsupload, methods=[POST, GET]) def jsupload(): return render_template(js_upload.html)1.2.3.

而返回的这个页面也很简单,包含一个 form,用来提交数据的。

复制<form id= "uploadForm"> <p >指定用户名: <input type="text" name="filename" value= "" id="UID"/></p> <p >上传文件: <input type="file" name="file" id="PID"/></p> <input type="button" value="上传" onclick="upload()" /> </form>1.2.3.4.5.

服务起来之后大概是这样的

不要嫌弃它丑,功能够了就行了。

这样一个简单的测试server就好了。

3.前端代码

前端代码使用 Ajax 来提交数据和回显数据

复制<script type="text/javascript"> function upload(){ //var formData = new FormData($( "#uploadForm" )[0]); var img_file = document.getElementById("PID"); var fileObj = img_file.files[0]; var formData = new FormData(); formData.append("UID", $("#UID").val()); formData.append("PID", fileObj); $.ajax({ method: "POST", url: "http://127.0.0.1:9980/api/test", timeout: 10000, data: formData, async: false, headers: {"client-type":"platform",}, dataType: "json", contentType:false, processData:false,//数据不做预处理 success: function(res) { return; }, error: function(e){ alert(e.msg); } }).done(function(res){ var result = ; var result1 = ; result += <img src=" + res[p_url] + " width="100">; $(#result).html(result); } ); } </script>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.

代码都是比较基础的,定位元素,调用函数,说下这里的 url,那个就是我在本地启动的 API server 的地址喽。同时这里还在监听服务器的返回,获取到返回的 p_url,来显示图片。

4. 后端代码

首先判断下前端传的是否是图片文件,如果不是直接返回错误

复制if PID not in request.files: return jsonify({code: -1, filename: , msg: please select one picture to upload})1.2.

如果判断通过,就获取图片和用户名称

复制user = request.form.get(UID) f = request.files[PID]1.2.

然后在本地创建目录用于保存图片,并且着手处理 User 和 Picture 的关系

复制basepwd = os.getcwd() pwd = os.path.join(basepwd, rapp) tmp_path = os.path.join(pwd, rstatic/%s % user) new_filename = str(time.time()) + . + f.filename.split(.)[1] if not os.path.exists(tmp_path): os.makedirs(tmp_path) upload_path = os.path.join(tmp_path, secure_filename(new_filename)) f.save(upload_path) if User.query.filter_by(username=user).first(): u = User.query.filter_by(username=user).first() u.picture_count += 1 p = Picture(picture_name=user, picture=upload_path, picture_id=u.id) db.session.add(u) db.session.add(p) db.session.commit()1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

如果不存在目录则创建,并且保存图片。如果用户存在于数据库中,那么 picture_count 加1,同时更新 Picture 表,关联 picture_id 为 user_id。

如果用户不存在,那么先插入用户,提交,然后再更新 Picture 表

复制newu = User(username=user) db.session.add(newu) db.session.commit() newp = Picture(picture_name=user, picture=upload_path, picture_id=newu.id) db.session.add(newp) db.session.commit()1.2.3.4.5.6.

最后API返回p_url用于前端web展示

复制return jsonify({"p_url": http://127.0.0.1:9980/static/%s/ % user + new_filename})1.

5. 最终效果

最后的效果如下

同时在项目的 static 目录下,会产生每个用户的图片,因为图片的命名都使用了 time.time(),也就不存在重名覆盖的问题啦

6. 任重道远

这次的完善就到这里了,不过程序还是有很多问题的,比如已知的问题就有如果在web端不填写名字或者不选择图片,都会产生一些问题;同时还可以增加一些接口,比如获取用户所有图片等待,这些都留到后面再说吧

还有个严峻的问题,就是每次本地调测好之后,都要手动同步代码到远程服务器,非常之麻烦,虽然目前项目很小,但是 CI 还是很有必要的,后面就来聊聊怎么结合 GitHub 做持续集成吧

完整代码看这里: https://github.com/zhouwei713/mini_api

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:新技术——自动识别图片验证码、发票验证
下一篇:显示手机号码归属地,专业修改移动手机号归属地技巧分享
相关文章

 发表评论

暂时没有评论,来抢沙发吧~