图片上传
1. 服务器端(Django)
-
存储图片到本地服务器
#导入配置文件 import django_jobapp.settings as settings def upload(request): if request.method == 'POST': try: #此处可以接收文件和字符串 f1 = request.FILES['usericon'] usrid=request.POST.get('userid') #设置保存的文件名 fname = '%s/pic/%s' % (settings.STATICFILES_DIRS[0], f1.name) #由于文件是二进制流的方式,所有要用chunks() with open(fname, 'wb') as pic: for c in f1.chunks(): pic.write(c) return JsonResponse({"code": "808"}) except Exception as ex: print(ex) return JsonResponse({"code": "408"}) else: return JsonResponse({"code": "408"})
-
利用uuid生成唯一文件名
import uuid fname = '%s/pic/%s' % (settings.STATICFILES_DIRS[0], str(uuid.uuid4())+'.'+f1.name.split('.')[1])
2. 客户端
-
利用表单上传
<form action="http://127.0.0.1:8000/user/upload/" method="post" enctype="multipart/form-data"> <input type="text" value="user001" name="userid"> <input type="file" name="usericon"> <input type="submit"> </form>
-
利用Ajax上传图片
$('#btn-submit').click(function () { var formData = new FormData($( "#myform" )[0]); $.ajax({ url: 'http://127.0.0.1:8000/user/upload/' , type: 'POST', data: formData, async: false, cache: false, contentType: false, processData: false, success: function (returndata) { console.log(returndata); }, error: function (returndata) { console.log(returndata); } }); })
-
图片预览+Ajax上传完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>上传文件</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <style> .icon{ width: 200px; height: 200px; } #upload_file{ display: block; width: 200px; height: 200px; position: relative; z-index: 1; opacity: 0; } #preview{ width: 200px; height: 200px; background: grey; background: url("add.png"); background-repeat: no-repeat; background-position: center; position: relative; border: solid 1px rgba(128, 128, 128, 0.4); top: -200px; z-index: 0; } #preview img{ width: 100%; height: 100%; object-fit: cover; /*object-position: center 100px;*/ } </style> </head> <body> <form id="myform"> <input type="text" value="user001" name="userid"> <div class="icon"> <input type="file" name="usericon" id="upload_file"> <div id="preview"></div> </div> </div> <input type="button" value="提交" id="btn-submit"> </form> <script> $('#upload_file').change(function (e) { var file = e.target.files[0]; preview1(file); }) function preview1(file) { var img = new Image(); img.src = URL.createObjectURL(file); var url = img.src; var $img = $(img); img.onload = function () { URL.revokeObjectURL(url); $('#preview').empty().append($img); } } $('#btn-submit').click(function () { var formData = new FormData($( "#myform" )[0]); $.ajax({ url: 'http://127.0.0.1:8000/user/upload/' , type: 'POST', data: formData, async: false, cache: false, contentType: false, processData: false, success: function (returndata) { console.log(returndata); }, error: function (returndata) { console.log(returndata); } }); }) </script> </body> </html>
3. Vue.JS实现图片上传
<input name="file" type="file" accept="image/png,image/gif,image/jpeg" @change="update"/>
import axios from 'axios'
// 添加请求头
update (e) { // 上传照片
var self = this
let file = e.target.files[0]
/* eslint-disable no-undef */
let param = new FormData() // 创建form对象
//usericon通常就是file的name属性值
param.append('usericon', file, file.name) // 通过append向form对象添加数据
param.append('chunk', '0') // 添加form表单中其他数据
console.log(param.get('file')) // FormData私有类对象,访问不到,可以通过get判断值是否传进去
let config = {
headers: {'Content-Type': 'multipart/form-data'}
}
// 添加请求头
axios.post('http://127.0.0.1:8000/user/upload/', param, config)
.then(response => {
if (response.data.code === 0) {
self.ImgUrl = response.data.data
}
console.log(response.data)
})
}
4. 七牛云存储
-
云存储模型
https://developer.qiniu.com/kodo/manual/1205/programming-model
-
安装
pip install qiniu
-
通过服务器端上传到七牛(方式一)
思路是,先把前端上传的文件存在本地服务器,然后再上传到七牛云服务器
from qiniu import Auth, put_file, etag import qiniu.config def qiniuupload(request): if request.method == 'POST': try: # 需要填写你的 Access Key 和 Secret Key access_key = 'M1HuucZkH6llwMhDYI9n7um4bymn6IzmZxu-jgfw' secret_key = 'Hev51XD6vqBQ_WhxSuyMjNjpnbiFP0QXGQ0YUhLH' # 构建鉴权对象 q = Auth(access_key, secret_key) # 要上传的空间 bucket_name = 'jobapp' f1 = request.FILES['usericon'] # usrid=request.POST.get('userid') # 上传到七牛后保存的文件名 key = '%s/pic/%s' % (settings.MEDIA_ROOT, str(uuid.uuid4())+'.'+f1.name.split('.')[1]) # key = str(uuid.uuid4())+'.'+f1.name.split('.')[1] # 生成上传 Token,可以指定过期时间等 token = q.upload_token(bucket_name, key, 3600) #保存文件到服务器 with open(key, 'wb') as pic: for c in f1.chunks(): pic.write(c) # 要上传文件的本地路径 localfile = key ret, info = put_file(token, key, localfile) print('七牛云存储') print(info) assert ret['key'] == key assert ret['hash'] == etag(localfile) #此处要写加入数据库代码 domain='http://pgmso4nw8.bkt.clouddn.com/' return JsonResponse({"code": "908","url":domain+key}) except Exception as ex: print('error-------------------------') print(ex) return JsonResponse({"code": "408"}) else: return JsonResponse({"code": "408"})
-
通过服务器端上传到七牛(方式二)
思路,客户端先请求业务服务器拿到token,然后客户端直接上传的七牛云
客户端代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>上传文件-七牛</title> <style> .icon { width: 200px; height: 200px; } #upload_file { display: block; width: 200px; height: 200px; position: relative; z-index: 1; opacity: 0; } #preview { width: 200px; height: 200px; background: grey; background: url("文件上传/add.png"); background-repeat: no-repeat; background-position: center; position: relative; border: solid 1px rgba(128, 128, 128, 0.4); top: -200px; z-index: 0; } #preview img { width: 100%; height: 100%; object-fit: cover; /*object-position: center 100px;*/ } </style> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <div class="container"> <div class="mainContainer"> <form method="post" enctype="multipart/form-data" id="form" action="upload"> <div id="box2"> <button class="select-button">选择文件</button> <input class="file-input" type="file" id="select2" /> </div> </form> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script> <script src="js/qiniu.min.js"></script> <script> $("#select2").unbind("change").bind("change",function(){ var file = this.files[0]; var finishedAttr = []; var compareChunks = []; var observable; if (file) { $.ajax({ url: "http://127.0.0.1:8000/user/qiniutoken/?key="+file.name, success: function (res) { var token = res.uptoken; var domain = res.domain; var newname=res.key var newfile = new File([file], newname); alert(newfile.name); var config = { useCdnDomain: false, disableStatisticsReport: true, retryCount: 6, region: qiniu.region.z0 }; var putExtra = { fname: "", params: {}, mimeType: ["image/png", "image/jpeg", "image/gif"] }; var key = newfile.name; // 添加上传dom面板 putExtra.params["x:name"] = key.split(".")[0]; var subscription; // 调用sdk上传接口获得相应的observable,控制上传和暂停 observable = qiniu.upload(file, key, token, putExtra); subscription = observable.subscribe({ next(res){ // ... }, error(err){ alert('error!') }, complete(res){ alert('上传成功!') console.log(res) } }); } }) //end ajax } }) </script> </body>
服务器端代码
def qiniutoken(request): if request.method == 'GET': try: # 需要填写你的 Access Key 和 Secret Key access_key = 'M1HuucZkH6llwMhDYI9n7um4bymn6IzmZxu-jgfw' secret_key = 'Hev51XD6vqBQ_WhxSuyMjNjpnbiFP0QXGQ0YUhLH' filename=request.GET.get('key') print(filename) # 构建鉴权对象 q = Auth(access_key, secret_key) # 要上传的空间 bucket_name = 'jobapp' key = str(uuid.uuid4())+'.'+filename.split('.')[1] # 生成上传 Token,可以指定过期时间等 token = q.upload_token(bucket_name,key, 3600) #此处要写加入数据库代码 domain='http://pgmso4nw8.bkt.clouddn.com/' return JsonResponse({"uptoken": token,"domain":domain,"key":key}) except Exception as ex: print('error-------------------------') print(ex) return JsonResponse({"code": "408"}) else: return JsonResponse({"code": "408"})