目录

1.设置页面初始化

2.更新头像

  1.点击头像进入更新头像界面

  2.更新头像页面初始化

  3.更新头像页面CSS样式

  4.头像上传来源选择:相册/相机

  5.调用api提供的本地接口从相册/相机提取图片

  6.后端提供头像更新的接口

  7.前端基于axios上传图片数据

3.本地更新头像信息

  1.头像上传成功后-关闭页面/将头像数据存储在前端

  2.setting.js提供avatar_url头像访问地址

  3.后端提供展示头像的视图方法

  4.设置页面头像立即刷新

  5.前端页面显示当前登录用户的基本信息

  6.后端提供用户基本信息的API接口

1.设置页面初始化

1.设置页面setting.html初始化

APP项目中对于用户的退出登录,一般都在设置中进行。

客户端新增配置页面setting.html,代码:

<!DOCTYPE html>
<html>
<head>
<title>用户中心</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="bg">
<img src="../static/images/form_bg.png">
</div>
<!-- 1.设置页面的返回按钮 -->
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="form">
<div class="item avatar">
<span class="title">头像</span>
<span class="goto">&gt;</span>
<span class="value">
<img src="../static/images/avatar.png" alt="">
</span>
</div>
<div class="item">
<span class="title">昵称</span>
<span class="goto">&gt;</span>
<span class="value">iR.Poke</span>
</div>
<div class="item">
<span class="title">手机号</span>
<span class="goto">&gt;</span>
<span class="value">134****9284</span>
</div>
<div class="item">
<span class="title">登陆密码</span>
<span class="value"></span>
<span class="goto">&gt;</span>
</div>
<div class="item">
<span class="title">交易密码</span>
<span class="value"></span>
<span class="goto">&gt;</span>
</div>
<div class="item">
<span class="title">地址管理</span>
<span class="value"></span>
<span class="goto">&gt;</span>
</div>
<div class="item">
<span class="title">设备管理</span>
<span class="value"></span>
<span class="goto">&gt;</span>
</div>
<div class="item logout">
<!-- 2.设置页面的切换账号 -->
<img @click="change_account" src="../static/images/change_account.png" alt="">
<!--3.设置页面的退出账号 -->
<p @click="logout">退出账号</p>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
prev:{name:"",url:"",params:{}},
current:{name:"setting",url:"setting.html",params:{}},
}
},
methods:{
goto_home(){
// 回到个人中心界面
this.game.goFrame("user","user.html",this.current);
},
change_account(){
// 切换账号
this.game.goFrame("login","login.html", this.current);
},
logout(){
// 退出账号
api.actionSheet({
title: '您确认要退出当前登录吗?',
cancelTitle: '取消',
destructiveTitle: '退出登录'
}, (ret, err)=>{
if( ret ){
this.game.print(ret);
if(ret.buttonIndex==1){
this.game.save({"access_token":"","refresh_token":""});
this.game.fremove(["access_token","refresh_token"]);
this.game.outWin("user");
}
}
}); }
}
});
}
</script>
</body>
</html>

设置页面setting.html初始化

2.设置页面的CSS样式

static/css/main.css,样式代码:

.setting .bg img{
animation: normal;
}
.setting .back{
top: 4rem;
}
.setting .form {
top: 9rem;
}
.setting .form .item{
height: 3.9rem;
line-height: 3.9rem;
font-size: 1.25rem;
text-indent: 0.6rem;
border-bottom: 1px solid rgba(204,153,102,0.2);
}
.setting .form .avatar{
height: 6.11rem;
line-height: 6.11rem;
}
.setting .form .avatar img{
width: 4.56rem;
height: 4.56rem;
vertical-align: middle;
}
.setting .form .item .value,
.setting .form .item .goto{
float: right;
}
.setting .form .logout{
margin-top: 3rem;
text-align: center;
height: 4rem;
line-height: 2rem;
}
.setting .form .logout img{
width: 11rem;
}

设置页面的CSS样式

3.用户界面点击设置按钮跳转到设置界面

<!-- 点击设置按钮去到设置界面 -->
<img class="setting" @click="goto_setting" src="../static/images/setting.png" alt=""> <script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
prev:{name:"",url:"",params:{}},
current:{name:"user",url:"user.html",params:{}},
}
},
methods:{
goto_setting(){
this.game.goFrame("setting","setting.html", this.current);
}
}
});
}
</script>
</body>
</html>

2.更新头像

1.点击头像进入更新头像界面

点击头像进入更新头像页面,setting.html,代码:

<span class="value">
<!-- 点击头像进入到更新头像界面 -->
<img @click="update_avatar_frame" src="../static/images/avatar.png" alt="">
</span> <script> update_avatar_frame(){
// 点击头像,跳到更新头像的界面:avatar.html
this.game.goFrame("avatar","avatar.html", this.current,null,{
type:"push", //动画类型(详见动画类型常量)
subType:"from_top", //动画子类型(详见动画子类型常量)
duration:300 //动画过渡时间,默认300毫秒
})
} </script>

2.更新头像页面初始化

avatar.html,显示页面,代码:

<!DOCTYPE html>
<html>
<head>
<title>用户中心</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar" id="app">
<div class="box">
<p class="title">上传头像</p>
<img class="close" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
prev:{name:"",url:"",params:{}},
current:{name:"avatar",url:"avatar.html",params:{}},
}
},
methods:{
update_avatar_confirm(){
// 确认上传头像 },
upload_avatar(ret){
// 头像上传处理 }
}
});
}
</script>
</body>
</html>

更新头像页面avatar.html初始化

3.更新头像页面CSS样式

main.css,页面样式,代码:

.avatar.frame{
background-color: rgba(0,0,0,0.6);
}
.avatar{
overflow: hidden;
}
.avatar .box{
width: 28.89rem;
height: 34.44rem;
background: url("../images/board_bg1.png") no-repeat 0 0;
background-size: 100%;
position: absolute;
top: 11rem;
margin: 0 auto;
left: 0;
right: 0;
} .avatar .box .title{
color: #fff;
font-size: 2rem;
text-align: center;
margin-top: 2.8rem;
}
.avatar .box .close{
width: 5.22rem;
height: 5.78rem;
position: absolute;
right: 0;
top: 8rem;
}
.avatar .box .header{
margin-top: 3.6rem;
font-size: 1.8rem;
text-align: center;
color: #ff3333;
font-weight: bold;
}
.avatar .box .text{
width: 16.67rem;
margin: 1.4rem auto 0;
font-size: 1.22rem;
color: #ffffcc;
}
.avatar .box .btn{
display: block;
width: 12.22rem;
height: 4.55rem;
margin: 1.4rem auto 0;
}

更新头像页面CSS样式

4.头像上传来源选择:相册/相机

头像上传来源选择,avatar.html,代码:

<!-- 1.关闭更新头像界面: close_frame -->
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<!-- 2.头像上传来源选择 :相册/相机 -->
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div> <script> close_frame(){
this.game.outFrame("avatar");
}, update_avatar_confirm(){
// 确认上传头像的方式
api.actionSheet({
title: '请选择上传头像的来源',
cancelTitle: '取消',
buttons: ['相册','相机'],
}, function(ret, err){
if( ret ){
alert( JSON.stringify( ret ) );
}else{
this.game.print( err );
}
}); }, </script>

5.调用api提供的本地接口从相册/相机提取图片

接下来,调用apicloud提供的本地接口从相册或者相机中提取图片.

avatar.html代码

<!-- 1.关闭更新头像界面: close_frame -->
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<!-- 2.头像上传来源选择 :相册/相机 -->
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div>
<script> close_frame(){
this.game.outFrame("avatar");
},
update_avatar_confirm(){
// 确认上传头像的方式
api.actionSheet({
title: '请选择上传头像的来源',
cancelTitle: '取消',
buttons: ['相册','相机'],
}, (ret, err)=>{
if( ret ){
var sourceType = ["album","camera"];
if(ret.buttonIndex > sourceType.length){
// 如果用户选择了取消,则关闭当前修改头像的页面
this.game.outFrame("avatar");
return;
}
// ***使用APIcloud提供的api.getPicture方法从相机/相册获取图片***
api.getPicture({
sourceType: sourceType[ret.buttonIndex-1],
mediaValue: 'pic',
destinationType: 'base64',
allowEdit: true,
preview:true,
quality: 50,
targetWidth: 100,
targetHeight: 100,
saveToPhotoAlbum: true,
}, (ret, err)=>{
if(ret){
this.game.print(ret);
}else{
this.game.print(err);
}
}); alert( JSON.stringify( ret ) );
}else{
this.game.print( err );
}
}); },
upload_avatar(ret){
// 头像上传处理 }
}
});
}
</script>
</body>
</html>

6.后端提供头像更新的接口

服务端提供头像更新接口,application/apps/users/views.py,代码

import base64, uuid,os
@jsonrpc.method("User.avatar.update")
@jwt_required # 验证jwt
def update_avatar(avatar):
"""获取用户信息"""
# 1.接受客户端上传的头像信息
ext = avatar[avatar.find("/")+1:avatar.find(";")] # 资源格式:jpeg/jpg/png....
b64_avatar = avatar[avatar.find(",")+1:]
b64_image = base64.b64decode(b64_avatar) # 2.使用uuid给头像文件生成随机的文件名
filename = uuid.uuid4() # 3.拼接头像文件在后端存储的路径
static_path = os.path.join( current_app.BASE_DIR,current_app.config["STATIC_DIR"] )
with open("%s/%s.%s" % (static_path, filename,ext),"wb") as f:
f.write(b64_image) # 4.查询当前用户是否存在
current_user_id = get_jwt_identity()
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
} # 5.将用户的头像数据存储到mysql数据库中
user.avatar = "%s.%s" % (filename,ext)
db.session.commit()
return {
"errno": status.CODE_OK,
"errmsg": message.avatar_save_success,
"avatar": "%s.%s" % (filename,ext)
}

在项目后端全局配置文件中添加静态文件目录存储路径

application/settings/__init__.py,代码:

# 静态文件目录存储路径
STATIC_DIR = "application/static"

7.前端基于axios上传图片数据

客户端基于axios上传图片数据,avatar.html代码

<!-- 1.关闭更新头像界面: close_frame -->
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<!-- 2.头像上传来源选择 :相册/相机 -->
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div>
<script> close_frame(){
this.game.outFrame("avatar");
},
update_avatar_confirm(){
api.actionSheet({
title: '请选择上传头像的来源',
cancelTitle: '取消',
buttons: ['相册','相机'],
}, (ret, err)=>{
if( ret ){
var sourceType = ["album","camera"];
if(ret.buttonIndex > sourceType.length){
this.game.outFrame("avatar");
return;
}
api.getPicture({
...
}, (ret, err)=>{
if(ret){
// 1.获取本地图片成功后,开始上传图片
this.upload_avatar(ret);
}else{
this.game.print(err);
}
}); }else{
this.game.print( err );
}
}); },
// 头像上传处理
upload_avatar(ret){ var token = this.game.get("access_token") || this.game.fget("access_token");
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
// 2.前端基于axios上传头像
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.avatar.update",
"params": {
"avatar": ret.base64Data,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.game.print(response);
}else{
this.game.print(response.data.result);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
})
}
}
});
}
</script>
</body>
</html>

3.本地更新头像信息

1.头像上传成功后-关闭页面/将头像数据存储在前端

关闭avatar.html页面,展示底下的setting.html,并将头像存储在前端

客户端的avatar.html代码:

upload_avatar(ret){
// 头像上传处理
var token = this.game.get("access_token") || this.game.fget("access_token");
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.avatar.update",
"params": {
"avatar": ret.base64Data,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
// 当后端存储头像数据成功后
if(parseInt(response.data.result.errno)==1000){
// 1.将头像存储在前端
this.game.fsave({"avatar": response.data.result.avatar});
// 2.跳转到设置页面
this.game.goFrame("setting","setting.html", this.current);
}else{
this.game.print(">>>> fail");
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
})
}
}
});
}

2.setting.js提供avatar_url头像访问地址

客户端的配置文件static/js/settings.js新增配置项avatar_url提供头像访问地址,代码;

function init(){
if(Game){
var game = new Game("../mp3/bg1.mp3");
Vue.prototype.game = game;
}
if(axios){
// 初始化axios
axios.defaults.baseURL = "http://192.168.20.251:5000/api" // 服务端api接口网关地址
axios.defaults.timeout = 2500; // 请求超时时间
axios.defaults.withCredentials = false; // 跨域请求资源的情况下,忽略cookie的发送
Vue.prototype.axios = axios;
Vue.prototype.uuid = UUID.generate;
}
// 接口相关的配置项
Vue.prototype.settings = {
captcha_app_id: "2071340228", // 腾讯防水墙验证码应用ID
avatar_url: "http://192.168.20.251:5000/users/avatar", // ***头像前端访问地址***
}
}

3.后端提供展示头像的视图方法

服务端提供展示头像的视图方法地址

application/apps/users/urls.py,代码:

from . import views
from application.utils import path
urlpatterns = [
path("/avatar", views.avatar),
]

确认总路由设置了访问蓝图的url前缀,application/urls.py,代码:

from application.utils import include
urlpatterns = [
include("","home.urls"),
include("/users","users.urls"),
include("/marsh","marsh.urls"),
]

视图中, 显示图片时验证用户身份.,application/apps/users/views.py代码:

from flask import make_response,request
@jwt_required # 验证jwt
def avatar():
"""获取头像信息""" # 1.获取前端存储头像的sign参数
avatar = request.args.get("sign") # 2.获取头像文件格式:jpg/jpeg/png
ext = avatar[avatar.find(".")+1:] # 3.获取头像文件的文件名
filename = avatar[:avatar.find(".")] # 4.后端文件存储的路径
static_path = os.path.join(current_app.BASE_DIR, current_app.config["STATIC_DIR"]) # 5.读取后端文件数据
with open("%s/%s.%s" % (static_path,filename,ext), "rb") as f:
content = f.read() # 此时content存储的是二进制文件
response = make_response(content) #
response.headers["Content-Type"] = "image/%s" % ext
return response

4.设置页面头像立即刷新

完成了上面步骤代码以后, 我们现在能在客户端修改用户头像了,但是在关闭avatar.html页面以后, setting.html页面中的头像并没有及时发生变化,.所以我们在avatar.html页面更新了头像以后, 我们借住apicloud提供的自定义事件和事件监听接口,来实现,通知setting.html页面,用户头衔已经发生改变了.

文档: https://docs.apicloud.com/Client-API/api#72

当前功能,我们需要根据文档了解关于sendEventaddEventListener的使用.

// a页面可以通过sendEvent发起一个自定义事件
api.sendEvent({
name: 'myEvent', # 自定义事件名称
extra: {
key1: 'value1', # 事件传参
key2: 'value2'
}
}); // b页面可以通过addEventListener进行监听是否有对应名称的自定义事件进行发送了,一旦监听到,则自动执行回调函数:
api.addEventListener({
name: 'myEvent' # 监听指定名称的事件
}, function(ret, err) { # ret接收指定名称的事件参数
alert(JSON.stringify(ret.value));
}); // c页面也可以通过addEventListener进行监听是否有对应名称的自定义事件进行发送了,一旦监听到,则自动执行回调函数:
api.addEventListener({
name: 'myEvent'
}, function(ret, err) {
alert(JSON.stringify(ret.value));
}); // b.c 页面都将收到 myEvent 事件

1.avatar.html发送自定义事件

接下来,我们就可以在avatar.html页面中,发送一个自定义事件,告知其他页面,当前用户的头像发生了改变.

avatar.html代码

        upload_avatar(ret){
// 头像上传处理
var token = this.game.get("access_token") || this.game.fget("access_token");
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.avatar.update",
"params": {
"avatar": ret.base64Data,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.game.fsave({"avatar": response.data.result.avatar});
// ***发送自定义事件***
api.sendEvent({
name: 'change_avatar',
extra: {
"avatar": response.data.result.avatar
}
});
this.game.outFrame("avatar");
}else{
this.game.print(">>>> fail");
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
})
}
}
});
}

2.setting.html监听自定义事件

setting.html页面中,监听自定义事件,这个监听过程是不需要刷新页面的.

methods:{
change_avatar(){
// 监听自定义事件
api.addEventListener({
name: 'change_avatar'
}, (ret, err)=>{
if( ret ){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.avatar = `${this.settings.avatar_url}?sign=${ret.value.avatar}&token=${token}`;
}
});
},

5.前端页面显示当前登录用户的基本信息

setting.html页面提供当前登陆用户的基本信息,代码:

      </div>
<div class="item">
<span class="title">昵称</span>
<span class="goto">&gt;</span>
<span class="value">{{nickname}}</span>
</div>
<div class="item">
<span class="title">手机号</span>
<span class="goto">&gt;</span>
<span class="value">{{mobile}}</span>
</div> <script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
nickname: "", // 昵称
mobile: "", // 手机号
avatar: "../static/images/avatar.png",
prev:{name:"",url:"",params:{}},
current:{name:"setting",url:"setting.html",params:{}},
}
},
created(){
this.get_user_info(); // 触发获取用户信息方法
this.change_avatar();
},
methods:{
// 获取当前用户登录基本信息
get_user_info(){
var token = this.game.get("access_token") || this.game.fget("access_token");
// 获取当前登陆用户基本信息
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.info",
"params": {}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
var res = response.data.result;
if(parseInt(res.errno) === 1000){
this.nickname = res.nickname;
// avatar从前端获取传到:src上
this.avatar = `${this.settings.avatar_url}?sign=${res.avatar}&token=${token}`;
this.mobile = res.mobile;
}
})
}, </script>
</body>
</html>

6.后端提供用户基本信息的API接口

服务端提供用户基本信息APi接口,application/apps/users/views.py,代码:

from .marshmallow import UserInfoSchema
@jsonrpc.method("User.info")
@jwt_required # 验证jwt
def info():
"""获取用户信息"""
current_user_id = get_jwt_identity() # 根据token反解出当前用户id # 判断当前用户是否存在
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
}
uis = UserInfoSchema()
data = uis.dump(user) # 将用户信息序列化传递给前端
return {
"errno": status.CODE_OK,
"errmsg": message.ok,
**data
}

marshmallow.py,代码:

from marshmallow import post_dump
class UserInfoSchema(SQLAlchemyAutoSchema):
id = auto_field()
mobile = auto_field()
nickname = auto_field()
avatar = auto_field() class Meta:
model = User
include_fk = True
include_relationships = True
fields = ["id","mobile","nickname","avatar"]
sql_session = db.session @post_dump()
def mobile_format(self, data, **kwargs):
data["mobile"] = data["mobile"][:3]+"****"+data["mobile"][-4:]
return data

day105:Mofang:设置页面初始化&更新头像/上传头像&设置页面显示用户基本信息的更多相关文章

  1. php头像上传预览

    php头像上传带预览: 说道上传图片,大家并不陌生,不过,在以后开发的项目中,可能并不会让你使用提交刷新页面式的上传图片,比如上传头像,按照常理,肯定是在相册选择照片之后,确认上传,而肯定不会通过fo ...

  2. Django 自带 user 字段扩展及头像上传

    django 及 rest_framework 笔记链接如下: django 入门笔记:环境及项目搭建 django 入门笔记:数据模型 django 入门笔记:视图及模版 django 入门笔记:A ...

  3. spring--mvc添加用户及用户头像上传

    spring--mvc添加用户及用户头像上传 添加用户步骤: 1.用ajax获取省份信息 2.添加用户 代码:register.jsp <meta http-equiv="Conten ...

  4. Django实现注册页面_头像上传

    Django实现注册页面_头像上传 Django实现注册页面_头像上传 1.urls.py 配置路由 from django.conf.urls import url from django.cont ...

  5. vue中使用axios post上传头像/图片并实时显示到页面

    在前端开发中,为了更好的用户体验,在头像上传时会先将图片显示到页面然后点击保存按钮 完成图片的上传成功 代码部分有参考他人的写法. html代码:   <div id="myPhoto ...

  6. 强大的flash头像上传插件(支持旋转、拖拽、剪裁、生成缩略图等)

    今天介绍的这款flash上传头像功能非常强大,支持php,asp,jsp,asp.net 调用 头像剪裁,预览组件插件. 本组件需要安装Flash Player后才可使用,请从http://dl.pc ...

  7. 【Bootstrap-插件使用】Jcrop+fileinput组合实现头像上传功能

    作者:Dreawer链接:https://zhuanlan.zhihu.com/p/24465742来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者:梦游的龙猫(转 ...

  8. [Bootstrap-插件使用]Jcrop+fileinput组合实现头像上传功能

    很久没有更新博客了,再不写点东西都烂了. 这次更新一个小内容,是两个插件的组合使用,实现头像上传功能. 业务需求: 头像上传功能,要对上传的文件进行剪切,且保证头像到服务器时必须是正方形的. 优化&l ...

  9. python 全栈开发,Day86(上传文件,上传头像,CBV,python读写Excel,虚拟环境virtualenv)

    一.上传文件 上传一个图片 使用input type="file",来上传一个文件.注意:form表单必须添加属性enctype="multipart/form-data ...

随机推荐

  1. Serilog 源码解析——数据的保存(上)

    在上一篇中,我们主要研究了Serilog是如何解析字符串模板的,它只是单独对字符串模板的处理,对于日志记录时所附带的数据没有做任何的操作.在本篇中,我们着重研究日志数据的存储方式.(系列目录) 本篇所 ...

  2. innodb为什么需要doublewrite(转)

    InnoDB的page size默认是16KB,而操作系统的一个block size是4KB,磁盘io block则更小.那么InnoDB的page刷到磁盘上要写4个操作系统block,在极端情况下( ...

  3. 运维和shell

    什么是运维 术语名词 IDC--(Internet Data Center)互联网数据中心,主要服务包括整机租用.服务器托管.机柜租用.机房租用.专线接入和网络管理服务等.广义上的IDC业务,实际上就 ...

  4. MTK官方SDK包编译openwrt

    全过程需要联网,最好有梯子,编译方式有两种 安装依赖库: apt-get install g++ apt-get install libncurses5-dev apt-get install zli ...

  5. 熬夜肝出5大点,18张图带你彻底弄懂MySQL事务日志

    在当今社会,充斥着大量的数据.从众多APP上的账户资料到银行信用体系等个人档案,都离不开对大量数据的组织.存储和管理.而这,便是数据库存在的目的和价值.目前数据库的类型主要分为两种,一种是关系型数据库 ...

  6. Flink处理函数实战之一:深入了解ProcessFunction的状态(Flink-1.10)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. Microsoft Visual C++ 2005 SP1无法安装

    安装时出现需要Microsoft Visual C++ 2005 Redistributble对话框, 里面说Command line option syntax error . Type Comma ...

  8. kettle——转换案例

    把stu1的数据按id同步到stu2,stu2有相同id则更新数据 (1)在mysql中创建两张表 mysql> create database kettle; mysql> use ke ...

  9. Mysql数据安全备份

    数据安全备份的意义 在出现意外的时候(硬盘损坏.断点.黑客攻击),以便数据的恢复 导出生产的数据以便研发人员或者测试人员测试学习 高权限的人员那操作失误导致数据丢失,以便恢复 备份类型 完全备份:对整 ...

  10. 面试官:小伙子,给我说一下mysql 乐观锁和悲观锁吧

    悲观锁介绍 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中, 将数据处于锁定状态.悲观锁的实现,往往依靠数据库 ...