前后台分离式开发(文件的上传下载),cookie(存放在前台),session(存放在后台)

Posted liuxiaolu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前后台分离式开发(文件的上传下载),cookie(存放在前台),session(存放在后台)相关的知识,希望对你有一定的参考价值。

一:前后台分离开发的概念

1.前台页面运行在前台服务器上,负责页面的渲染(静态文件的加载)与转跳

2.后台代码运行在后台服务器上,负责数据的处理(提供数据请求的接口)

主要代码(前端中要导入bootstrap):

前端:

技术图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
    <link rel="stylesheet" href="./bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>

<button class="btn btn-primary">主页</button>
<a href="./login.html">登录页面</a>
<a href="./upload.html">上传页面</a>
<a href="http://127.0.0.1:8731/download">链接标签页面</a>
<button class="btn">普通标签页面</button>
<script src="bootstrap-3.3.7-dist/js/jquery-3.3.1.js"></script>
<script>
    $(.btn).click(function () {
        window.location.href=http://127.0.0.1:8731/dowmload/
    })
</script>

</body>
</html>
index
技术图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<h1>登录页面</h1>
<form action="">
    <input class="usr" type="text" name="usr">
    <input class="pwd" type="password" name="pwd">
    <input class="btn" type="button" value="登录">
</form>
</body>
<script src="bootstrap-3.3.7-dist/js/jquery-3.3.1.js"></script>
<script>
    $(.btn).click(function () {
        $.ajax({
            url:http://127.0.0.1:8731/login/,
            type:post,
            data:{
                usr:$(.usr).val(),
                pwd:$(.pwd).val()
            },
            success:function (data) {
                console.log(data);
                // 可以完成页面的局部刷新
                if (data.status == ok) {
                    $(h2).text(data.usr)
                }
            }
        })
    })
</script>
</html>
login
技术图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upload</title>
</head>
<body>

<form action="">
    <input type="file" class="file" multiple>
    <input class="btn" type="button" value="上传">
</form>
<script src="bootstrap-3.3.7-dist/js/jquery-3.3.1.js"></script>
<script>
    // $(.btn).click(function () {
    //     var file = $(.file).get(0).files[0];//js对象下files的第一个文件
    //     console.log(file)
    //
    // })

        $(.btn).click(function () {
        // alert(开始上传)
        // var file = $(.file).get(0).files[0];  // js对象下files中的第一个文件
        // console.log(file);
        // var form_data = new FormData();
        // form_data.append(file, file);
        var files = $(.file).get(0).files;
        for (var i = 0; i < files.length; i++) {
            var form_data = new FormData();
            form_data.append(file, files[i]);
            upload_action(form_data)
        }
    });

    function upload_action(form_data) {
        $.ajax({
            url: http://127.0.0.1:8731/upload/,
            type: post,
            // data: 文件信息,
            data: form_data,
            // 告诉jq,不需要帮我们再处理数据及数据格式
            contentType: false,
            processData: false,
            success: function (data) {
                console.log(data);
            }
        })
    }
</script>

</body>
</html>
upload

后台:

技术图片
from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
# Create your views here.


def login(request):
    # 假设数据库存放的用户信息为 abc:123
    if request.method=="POST":
        usr=request.POST.get(usr,None)
        pwd=request.POST.get(pwd,None)
        if usr==abcand pwd==123:
            return JsonResponse({status:ok,usr:usr})
    return JsonResponse({status: error, usr: None})


def upload(request):
    file_io = request.FILES.get(file, None)
    print(file_io)
    if file_io:
        with open(file_io.name, wb) as f:
            for line in file_io:
                f.write(line)

    return JsonResponse({status: error, msg: 上传成功})

# 下载
from django.http import FileResponse
def download(request):
    # 此处固定死了文件(写死了)
    file = open(123.md, rb)
    response = FileResponse(file)
    # 设置响应文件类型数据的响应头
    response[Content-Type] = application/octet-stream
    response[Content-Disposition] = attachment;filename="%s" % file.name
    return response
views

settings设置(设置跨域问题):

技术图片

要允许跨域源:

CORS_ORIGIN_ALLOW_ALL = True

要记得去url中配置路由

 二:跨域请求数据

  通常情况下,A网页访问B服务器资源时,不满足以下三个条件其一就是跨域访问:

    1.协议不同

    2.端口不同

    3.主机不同

  Django解决跨域问题:

技术图片
安装django-cors-headers模块

在settings.py中配置
# 注册app
INSTALLED_APPS = [
    ...
    corsheaders
]
# 添加中间件
MIDDLEWARE = [
    ...
    corsheaders.middleware.CorsMiddleware
]
# 允许跨域源
CORS_ORIGIN_ALLOW_ALL = True
跨域问题解决

技术图片

技术图片

技术图片

三:文件上传

浏览器:

技术图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upload</title>
</head>
<body>

<form action="">
    <input type="file" class="file" multiple>
    <input class="btn" type="button" value="上传">
</form>
<script src="bootstrap-3.3.7-dist/js/jquery-3.3.1.js"></script>
<script>
    // $(.btn).click(function () {
    //     var file = $(.file).get(0).files[0];//js对象下files的第一个文件
    //     console.log(file)
    //
    // })

        $(.btn).click(function () {
        // alert(开始上传)
        // var file = $(.file).get(0).files[0];  // js对象下files中的第一个文件
        // console.log(file);
        // var form_data = new FormData();
        // form_data.append(file, file);
        var files = $(.file).get(0).files;
        for (var i = 0; i < files.length; i++) {
            var form_data = new FormData();
            form_data.append(file, files[i]);
            upload_action(form_data)
        }
    });

    function upload_action(form_data) {
        $.ajax({
            url: http://127.0.0.1:8731/upload/,
            type: post,
            // data: 文件信息,
            data: form_data,
            // 告诉jq,不需要帮我们再处理数据及数据格式
            contentType: false,
            processData: false,
            success: function (data) {
                console.log(data);
            }
        })
    }
</script>

</body>
</html>
upload

后台:

def upload(request):
    file = request.FILES.get(file, None)
    if file:
        with open(file.name, wb) as f:
            for line in file:
                f.write(line)
    return JsonResponse({
        status: OK,
        msg: upload success
    })

四:文件下载

浏览器:

<a href="http://127.0.0.1:8121/download/">下载</a>
<button type="button" class="download">下载</button>
<script>
    $(.download).click(function () {
        location.href = http://127.0.0.1:8121/download/
    })
</script>

后台:

def download(request):
    file = open(123.zip, rb)
    response = FileResponse(file)
    response[Content-Type] = application/octet-stream
    response[Content-Disposition] = attachment;filename="%s" % file.name
    return response

五:cookie

  cookie:前端浏览器以明文形式存放的具有key、value信息特征的字符串

  cookie的作用:在前后台均可以访问并设置cookie,从而解决HTTP协议的无状态特点导致先后两次请求无逻辑可寻问题(如:不同用户登录后,再进入个人主页,明显是有信息区别的)

  cookie简介:随着浏览器的发展,很多浏览器不再对cookie个数加以限制,但仍存在大小的限制,一般为4k;但为了达到传输的高效,服务器的解析速度,还是建议开发者严格控制cookie个数

  cookie初始:为页面文档document的一个字节属性:document.cookie = ‘key=value;‘

# Django用HttpResponse对象操作Cookie
response = HttpResponse(所有的响应都是HttpResponse对象)
# 设置cookie:key、vaule与过期时间
response.set_cookie(key, value, max_age)
# 删除cookie:key
response.delete_cookie(key)
# 设置加盐cookie:key、vaule与盐字符串(就是简易的加密)
response.set_signed_cookie(key, value, salt)

# 通过request对象获取Cookie
# 获取key对应的value
request.COOKIES.get(key, None)
# 获取加盐后的key对应的value
request.get_signed_cookie(key, salt)

‘‘‘
了解:set_cookie方法的其他参数
1. expires:过期时间,格式为字符串类型的时间
2. path:作用路径,/代表所有路径下均起作用
3. domain:作用域名
4. secure:布尔类型,浏览器是否通过HTTPS方式回传cookie
5. httponly:布尔类型,JS能否直接访问该条cookie
‘‘‘

cookie运用:

需求:

1. /index/访问主页(可直接访问),主页中存在四个转跳
    -- 登录(/login/)
    -- 个人主页(/user/)
    -- 订单详情(/order/)
    -- 注销(/logout/)
2. 进入个人主页、订单详情页面时,如果未登录,需先登录,然后自动回到个人主页或订单详情页面,反之直接进入

核心代码:

技术图片
# views.py
from django.shortcuts import render, redirect, HttpResponse

# 确认登录装饰器
def login_check(func):
    def inner(request, *args, **kwargs):
        is_login = request.COOKIES.get(is_login, False)
        # 确定当前被装饰的请求,登录完毕可以跳转回去
        url = request.get_full_path()
        if is_login:
            return func(request, *args, **kwargs)
        else:
            # 将回跳的路径作为参数(登录的表单action需要空着不写)
            return redirect(/login/?back_url=%s % url)
    return inner

# 主页
def index(request):
    return render(request, index.html)

# 登录页面
def login(request):
    if request.method == "GET":
        return render(request, login.html)
    if request.method == "POST":
        # 获取回跳的地址
        back_url = request.GET.get(back_url, /index/)
        usr = request.POST.get(usr, None)
        pwd = request.POST.get(pwd, None)
        if usr == abc and pwd == 123:
            # 确定回跳
            response = redirect(back_url)
            # 登录成功获取cookie
            for i in range(500):
                response.set_cookie(usr%i % i, usr)
            response.set_cookie(is_login, True)
            return response

@login_check
def order(request):
    print(request.COOKIES)
    usr = request.COOKIES.get(usr, None)
    return render(request, order.html, locals())

@login_check
def user(request):
    usr = request.COOKIES.get(usr, None)
    return render(request, user.html, locals())

def logout(request):
    response = HttpResponse(注销成功)
    response.delete_cookie(is_login)
    response.delete_cookie(usr)
    return response
核心代码

六:session

  什么是session:在后台通常以密文形式存放key、value形式数据,一个会话存放为数据库的一条字段

  session的作用:结合cookie使用,解决cookie的不安全性

  session简介:session是存放在服务器端的key-value形式的状态数据

技术图片
‘‘‘ 常用操作
# 1. 设置
request.session[‘key1‘] = ‘value1‘
request.session[‘key2‘] = ‘value2‘
# 过程:
# i) 生成一个随机字符串,作为主键
# ii) 在django_session表中插入有三个字段的一条数据(一条数据对应一个浏览器会话)
    -- session_key:主键-随机字符串
    -- session_data:该会话拥有的所有key-value形成的大字典的加密字符串
    -- expire_date:过去时间,默认14天
# iii) 往浏览器中写入一条cookie,sessionid=主键的随机字符串

2. 获取
request.session.get(‘key‘, None)

3. 删除
request.session.delete()  # 只删除当前会话对应的一条记录
request.session.flush()  # 除了删除当前会话对应的一条记录外,还删除对应浏览器中的cookie

5. 其他
request.session.session_key  # 获取当前会话对应的session_key
request.session.exists(‘session_key‘)  # 判断某session_key是否存在
request.session.clear_expired()  # 情况所有过去的Session
‘‘‘


‘‘‘ settings.py配置
# 1. 数据库存储
# SESSION_ENGINE = ‘django.contrib.sessions.backends.db‘  # 引擎(默认)
#
# 2. 缓存存储
# SESSION_ENGINE = ‘django.contrib.sessions.backends.cache‘  # 引擎
# SESSION_CACHE_ALIAS = ‘default‘  # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
#
# 3. 文件存储
# SESSION_ENGINE = ‘django.contrib.sessions.backends.file‘  # 引擎
# SESSION_FILE_PATH = ‘/‘  # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
#
# 4. 缓存 + 数据库存储
# SESSION_ENGINE = ‘django.contrib.sessions.backends.cached_db‘  # 引擎
#
# 5. 加密Cookie
# SESSION_ENGINE = ‘django.contrib.sessions.backends.signed_cookies‘  # 引擎
#
# SESSION_COOKIE_NAME = "sessionid"  # cookie的key名,值为随机字符串
# SESSION_COOKIE_PATH = "/"  # 作用路径,/代表所有路径下均起作用)
# SESSION_COOKIE_DOMAIN = None  # 作用域名
# SESSION_COOKIE_SECURE = False  # 布尔类型,浏览器是否通过HTTPS方式回传cookie
# SESSION_COOKIE_HTTPONLY = True  # 布尔类型,JS能否直接访问该条cookie
# SESSION_COOKIE_AGE = 1209600  # 数据库session字段的过期时间
# SESSION_EXPIRE_AT_BROWSER_CLOSE = True  # 浏览器关闭后cookie是否过期,默认False不过期
# SESSION_SAVE_EVERY_REQUEST = False  # 每一次请求,是否更新session字段的过期时间,默认False不更新

‘‘‘
session介绍

 

以上是关于前后台分离式开发(文件的上传下载),cookie(存放在前台),session(存放在后台)的主要内容,如果未能解决你的问题,请参考以下文章

在前后端分离的项目中,ajax跨域请求怎样附带cookie

采坑: 前后端分离 Cookie

聊一下,前后分离后带来的跨域访问和cookie问题

webuploader分片上传的实现代码(前后端分离)

springboot-vue前后端分离session过期重新登录的实现

完全前后端分离项目