前端传图片到python然后再存到七牛云

在网站开发中经常会遇到图片的上传和存储,最多的方案是图片存到服务器,然后数据库存地址,点开某一个页面时通过数据库的地址渲染到前端,但数据量大或者服务器吃力的情况下,图片渲染会很慢,所以最好的办法是选择云存储,以七牛云为例:

首先是前端代码(就简单来了,直接两个按钮怼上去)


```javascript
<!DOCTYPE html>
<html lang="en">
<head>
    <script src="/static/js/jquery-3.3.1.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="/static/js/jquery.cookie.js"></script>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="file" value="上传图片" id="upload">
<input type="button" id="checkimg" value="上传图片">


<script type="text/javascript">
    //上传图片
    $("#checkimg").click(function () {
        var img = $("#upload")[0].files[0];
        var formdata = new FormData;
        formdata.append("img", img);
        $.ajax({
                    cache: false,
                    type: "POST",
                    url: "/testone/first/",
                    data: formdata,
                    headers: {"X-CSRFToken": $.cookie('csrftoken')},
                    async: false,
                    contentType: false,
                    processData: false,
                    datatype: "json",
                    success: function (data) {
                        if (data.status_res == "success") {
                            alert("提交成功!")
                            window.location.href = "/failureProcess/failure_page/?failure_id={{ alarm.project_id }}"
                        } else if (data.status_res == "fail") {
                            alert("提交失败")
                        }
                    },
                    error: function () {
                        alert("连接失败")
                    }

                })

    });

</script>
</body>
</html>

在这里插入图片描述

后台代码(django框架)

import os
from utils import Uploadimg
from django.shortcuts import render

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
path = os.path.join(BASE_DIR, r'static\js')
# Create your views here.


def first(request):
    if request.method == "POST":
        img = request.FILES.get("img")
        up = Uploadimg.UploadImg(img)
        up.upload_toqiniu()
        return render(request, "first.html")
    else:
        return render(request, "first.html")

主要的逻辑代码

import os
from . import config
from qiniu import Auth, put_file, etag

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
path = os.path.join(BASE_DIR, r'static\img')


class UploadImg(object):
    """
    上传图片到七牛云
    """

    def __init__(self, file):
        """
        初始化key
        """
        self.access_key = config.ACCESS_KEY
        self.secret_key = config.SECRET_KEY
        self.check_key(self.access_key, self.secret_key)
        self.file = file  # UPload对象
        self.check_file(self.file)  # 文件对象
        self.save_local(file)

    @staticmethod
    def check_key(access_key, secret_key):
        """
        access_key和secret_key不能为空
        """
        if not (access_key and secret_key):
            raise ValueError('秘钥错误!')

    @staticmethod
    def check_file(file):
        """
        参数必须为文件, 以是否有name属性为判断标准
        """
        if not hasattr(file, "name"):
            raise ValueError("文件错误!")

    # TODO: 获取上传空间,供选择
    def select_bucket(self):
        pass

    def upload_toqiniu(self):  # 上传实例
        localfile = path + '\\' + self.file.name
        q = Auth(self.access_key, self.secret_key)  # 实例化q,调用七牛安全机制类
        bucket_name = 'ebeauty'  # 暂时使用这个空间
        key = self.file.name
        token = q.upload_token(bucket_name, key, 3600)
        ret, info = put_file(token, key, localfile)
        assert ret['key'] == key
        assert ret['hash'] == etag(localfile)
        self.del_lcoal()

    def save_local(self, file):  # 把图片暂存到本地
        for chunk in file.chunks():
            with open(path.replace("\\", "/") + "/" + self.file.name, "wb") as f:
                f.write(chunk)

    def del_lcoal(self):  # 把本地暂存的图片删除
        for maindir, a, file_name_list in os.walk(path):
            os.remove(maindir + "\\" + self.file.name)

    def database_url(self):  # 把图片路径存入数据库
        pass

这里有几个需要注意的点:

def put_file(up_token, key, file_path, params=None,
             mime_type='application/octet-stream', check_crc=False,
             progress_handler=None, upload_progress_recorder=None, keep_last_modified=False):
    """上传文件到七牛

    Args:
        up_token:         上传凭证
        key:              上传文件名
        file_path:        上传文件的路径
        params:           自定义变量,规格参考 http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
        mime_type:        上传数据的mimeType
        check_crc:        是否校验crc32
        progress_handler: 上传进度
        upload_progress_recorder: 记录上传进度,用于断点续传

    Returns:
        一个dict变量,类似 {"hash": "<Hash string>", "key": "<Key string>"}
        一个ResponseInfo对象
    """
    ret = {}
    size = os.stat(file_path).st_size
    # fname = os.path.basename(file_path)
    with open(file_path, 'rb') as input_stream:
        file_name = os.path.basename(file_path)
        modify_time = int(os.path.getmtime(file_path))
        if size > config._BLOCK_SIZE * 2:
            ret, info = put_stream(up_token, key, input_stream, file_name, size, params,
                                   mime_type, progress_handler,
                                   upload_progress_recorder=upload_progress_recorder,
                                   modify_time=modify_time, keep_last_modified=keep_last_modified)
        else:
            crc = file_crc32(file_path)
            ret, info = _form_put(up_token, key, input_stream, params, mime_type,
                                  crc, progress_handler, file_name,
                                  modify_time=modify_time, keep_last_modified=keep_last_modified)
    return ret, info

这是七牛云的sdk源码,可以看到他是从本地读取文件然后再上传的,所以后台接收到图片对象后要先在本地暂存一下:

    def save_local(self, file):  # 把图片暂存到本地
        for chunk in file.chunks():
            with open(path.replace("\\", "/") + "/" + self.file.name, "wb") as f:
                f.write(chunk)

等上传到七牛云之后再删除:

    def del_lcoal(self):  # 把本地暂存的图片删除
        for maindir, a, file_name_list in os.walk(path):
            os.remove(maindir + "\\" + self.file.name)

当然不删除也可以(主要是节省空间)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值