zoukankan      html  css  js  c++  java
  • js 上传文件,通过django存储到数据库,保存类型为blob类型

    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

    {#上传策略模态框#}
        <div class="modal fade" data-backdrop="static" id="upmodal" tabindex="-1" role="dialog"
             aria-labelledby="myModalLabel" aria-hidden="true">
            <div class="modal-dialog" style=" 450px;">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span></button>
                        <h4 class="modal-title">上传策略</h4>
                    </div>
                    <div class="modal-body" style="padding: 30px;height:auto">
                        <form>
                            <div style="margin-top:3%; display: block">
                                <label>策略名称</label>
                                <input class="opts form-control" id="stgname" name="stgname" type="text"
                                       placeholder="策略名称">
                            </div>
                            <div style="margin-top:3%"><label>指定服务器</label>
                                <select class="opts form-control" id="envname" name="envname">
                                    <option value="">-</option>
                                    {% for env in envs_obj %}
                                        {% if env.type == '1' %}
                                            <option name="envname" value="{{ env.envid }}">
                                                {{ env.envname }}
                                            </option>
                                        {% endif %}
                                    {% endfor %}
                                </select>
    
                            </div>
                            <div style="margin-top:3%"><label>策略组</label>
                                <select class="opts form-control" id="stggroup" name="stggroup">
                                    <option value="">-</option>
                                    <option name="isactive" value="1">
                                        做市策略
                                    </option>
                                    <option name="isactive" value="2">
                                        CTA策略
                                    </option>
                                    <option name="isactive" value="3">
                                        算法策略
                                    </option>
                                </select>
                            </div>
                            <div style="margin-top:3%"><label>选择文件</label>
                                <input class="opts form-control" id="file" name="file" type="file" accept=".py"
                                       placeholder="选择文件" onchange="filename1()">
                            </div>
                            <div style="margin-top:3%"><label>策略参数</label>
    
                                <table style="background-color: white">
                                    <thead>
                                    <tr class="activetable">
                                        <th>
                                            操作
                                        </th>
                                        <th>
                                            参数名*
                                        </th>
                                        <th>
                                            参数值*
                                        </th>
                                        <th>
                                            参数描述
                                        </th>
                                    </tr>
                                    </thead>
                                    <tbody id="tb1">
                                    <tr class="activetable">
                                        <td>
                                            <span style="padding:3px;cursor: pointer" class="btn-success small"
                                                  onclick="new_col('tb1')">新增行
                                            </span>
                                        </td>
                                        <td>
                                            <input class="activetable" name="stg_name" id="stg_name">
                                        </td>
                                        <td>
                                            <input class="activetable" name="stg_value" id="stg_value">
                                        </td>
                                        <td>
                                            <input class="activetable" name="stg_desc" id="stg_desc">
                                        </td>
                                    </tr>
                                    </tbody>
                                </table>
                            </div>
                            <div style="margin-top:3%">
                                <span style="margin-left:10%;cursor:pointer;padding:5px" class="btn-primary"
                                      onclick="sub(gets)">提交</span>
                                <span style="margin-left:60%;cursor:pointer;padding:5px" class="btn-success"
                                      onclick="fad_upmodeal_add_change()">取消</span>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    
    
    <!-- js部分--->
    <script type="text/javascript">
            //上传策略模态框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_
                        }
                    }
                }
            }
    </script>
    

    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,
                )
    
    '''
    总结:
    	此类问题可能出现在前端,也可能出现在后端,所以要想在最短的时间内定位出错误,就需要仔细分析(比如这个问题,源于文件大小的不同,但是只是有一点点不同,所以需要逆向思维,从数据库查出数据后,再和前端传来的数据作比较,这样就能快速找到问题,是前端的问题了)
    '''
    
  • 相关阅读:
    Android打包key密码丢失找回
    Java 操作 elasticsearch 报错(1)
    Linux Hbase1.2.6 安装及使用(1)
    JAVA WEB 作用域之间的区别
    JSTL 与 EL
    HTML CSS 常用单词
    java
    CentOS 7 MySQL 5.7 主从设置
    VMware安装CentOS7后配置静态IP
    MySQL explain,type分析(转)
  • 原文地址:https://www.cnblogs.com/michealjy/p/13227875.html
Copyright © 2011-2022 走看看