前端传图片到python然后再存到七牛云
程序员文章站
2022-07-05 18:43:27
...
在网站开发中经常会遇到图片的上传和存储,最多的方案是图片存到服务器,然后数据库存地址,点开某一个页面时通过数据库的地址渲染到前端,但数据量大或者服务器吃力的情况下,图片渲染会很慢,所以最好的办法是选择云存储,以七牛云为例:
首先是前端代码(就简单来了,直接两个按钮怼上去)
```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)
当然不删除也可以(主要是节省空间)
下一篇: 再抽两次