js 上传文件,通过django存储到数据库,保存类型为blob类型
"""
整体思路:
前端通过input框上传文件,然后通过reader读取文件,jq发送post请求到后台 ,后台通过orm存储到数据库blob文件
"""
'''
思考的几个坑点:
代码写完后,测试出现前端上传和数据库上传的文件大小不一致的问题,解决过程中有以下几个思路:
1.数据库存储的是blob类型,但是django model并没有对应的类型,所以猜测可能数据格式转换的差异导致的大小不一
答:通过数据库反向生成model得出Blob类型对应的是text类型,所以类型方面应该没有问题,此外,django直接用orm语句操作,类型转换方面也没有乱码,所以猜测不应该是后台的问题。(通过先读取数据库,拿到blob数据,看一下和我传过去的数据有什么区别,结果发现是少了一些换行符
)
2.猜测是前端上传数据的大小就不对。
答:通过查询得到上传文件直接val()取到的是文件路径,而不是文件的内容,然后找到读取文件的方法,声明一个reader对象,然后把文件传进去进行读取,在read.onload中接收数据;
在前端直接打印读取的文件时,发现大小并没有变化,所以上传的文件是没有问题的,但是因为一开始没想到read.onload里文件读取的值怎么传到sub提交函数中,所以用了老办法(就是将值先传给一个display:none的标签,然后再用选择器取值)
问题就出现在这里,因为赋值给标签,之后再取值会发现格式乱掉了,该有的
换行,都没有了,所以就想办法生成一个全局变量,用于存放上传的文件(注意,上传文件是在input的监听事件里,一有文件上传,就需要把值赋给全局变量),然后再把数据发给后台,就可以了。
'''
'''具体代码如下'''
paper.html
{#上传策略模态框#}
aria-labelledby="myModalLabel" aria-hidden="true">
//上传策略模态框input框的值,
function gets() {
//仿真策略参数表的条数[{key,value,desc},{}]
var pararry = []
$("#tb1").find("tr").each(function () {
var tdata = $(this).children()
var paraname = tdata.eq(1).find("input").val()
var paravalue = tdata.eq(2).find("input").val()
var paradesc = tdata.eq(3).find("input").val()
var paradic = {"paraname": paraname, "paravalue": paravalue, "paradesc": paradesc}
pararry.push(paradic)
})
data = {
'stgname': JSON.stringify([$('#stgname').val()]),
'envname': JSON.stringify([$('#envname').val()]),
'stggroup': JSON.stringify([$('#stggroup').val()]),
{#'file': JSON.stringify([file]),#}
'pararry': JSON.stringify(pararry)
}
return data;
}
//上传策略提交逻辑
function sub(func) {
data = func();
data['file'] = JSON.stringify([files])
{#console.log("xxxxxxxxxxx", files)#}
//对提交的数据进行遍历,json解析成数组取第一个值,然后取Bool值,
// 如果是false(空),则alert,并且返回空,不继续执行下面代码
for (let key in data) {
var item = JSON.parse(data[key])[0]
if (Boolean(item) == false && key != 'id') {
var title = $("#" + key).prev().text()
alert(title + "不能为空!")
return
}
}
$.post("{% url 'trade:paper' %}", data, function (r) {
if (r == 'y') {
//新建成功则跳转,否则传错误信息
window.location.reload();
} else {
window.location.reload();
}
});
}
//全局变量,用于取得上传的文件
var files = ""
//只能上传py文件
function filename1() {
var filename_ = $("#file").val()
{#var file = $("#file").files[0]#}
if (filename_ && filename_.slice(-3) != ".py") {
alert("请上传py为后缀的文件!")
$("#file").val("")
}
//文件上传(文件读取)
const file = document.getElementById("file").files[0];
{#console.log("file", file)#}
if (file) {
{#console.log("234")#}
var reader = new FileReader();
{#reader.readAsBinaryString(file);#} //乱码
{#reader.readAsDataURL(file); //需要base64解码,然后再解码(会有16进制的数据)#}
reader.readAsText(file, "utf-8"); //大小不一致
reader.onload = function () {
var file_ = reader.result
files = file_
{#console.log("files", file_)#}
if (file_){
{#console.log(file_)#}
return file_
}
}
}
}
paper.py
'''
基于web自动生成的策略编号赋值,
算法策略以50001开始递增,其他策略以10001开始递增
Strategy_ID = 10001
'''
# 上传策略,写入策略表,仿真策略审批表,仿真策略参数表
data = request.POST
stggroup_other = 10001
stggroup_sf = 50001
stggroup_3 = Strategy.objects.filter(stggroup='3').aggregate(Max('stgid'))
stggroup_1_2 = Strategy.objects.exclude(stggroup='3').aggregate(Max('stgid'))
if json.loads(data['stggroup'])[0] == '3':
# 算法策略组
if stggroup_3['stgid__max']:
stgid = stggroup_3['stgid__max'] + 1
else:
stgid = stggroup_sf
else:
# 非算法策略组
if stggroup_1_2['stgid__max']:
stgid = stggroup_1_2['stgid__max'] + 1 # int + int
else:
stgid = stggroup_other
filt = json.loads(data["file"])[0]
# print("这是前端传来的文件", filt )
# print(type(filt))
# 新增 策略表
createtime = chardate()
# x = Strategy.objects.values("stgfile").filter(stgid=10040)
# print(x)
Strategy.objects.create(
stgid=stgid,
stgname=json.loads(data["stgname"])[0],
stggroup=json.loads(data["stggroup"])[0],
stgfile=filt,
createtime=createtime,
backupdatetime=chardate(),
customerid=request.session.get('customerid', ''),
backtest=-1,
status='',
paperisdelete=1,
liveisdelete=1,
)
'''
总结:
此类问题可能出现在前端,也可能出现在后端,所以要想在最短的时间内定位出错误,就需要仔细分析(比如这个问题,源于文件大小的不同,但是只是有一点点不同,所以需要逆向思维,从数据库查出数据后,再和前端传来的数据作比较,这样就能快速找到问题,是前端的问题了)
'''