js 上傳文件,通過django存儲到數據庫,保存類型為blob類型


js 上傳文件,通過django存儲到數據庫,保存類型為blob類型

"""
整體思路:
	前端通過input框上傳文件,然后通過reader讀取文件,jq發送post請求到后台 ,后台通過orm存儲到數據庫blob文件
"""

'''
思考的幾個坑點:
	代碼寫完后,測試出現前端上傳和數據庫上傳的文件大小不一致的問題,解決過程中有以下幾個思路:
	1.數據庫存儲的是blob類型,但是django model並沒有對應的類型,所以猜測可能數據格式轉換的差異導致的大小不一
	答:通過數據庫反向生成model得出Blob類型對應的是text類型,所以類型方面應該沒有問題,此外,django直接用orm語句操作,類型轉換方面也沒有亂碼,所以猜測不應該是后台的問題。(通過先讀取數據庫,拿到blob數據,看一下和我傳過去的數據有什么區別,結果發現是少了一些換行符\r\n)
	2.猜測是前端上傳數據的大小就不對。
	答:通過查詢得到上傳文件直接val()取到的是文件路徑,而不是文件的內容,然后找到讀取文件的方法,聲明一個reader對象,然后把文件傳進去進行讀取,在read.onload中接收數據;
	在前端直接打印讀取的文件時,發現大小並沒有變化,所以上傳的文件是沒有問題的,但是因為一開始沒想到read.onload里文件讀取的值怎么傳到sub提交函數中,所以用了老辦法(就是將值先傳給一個display:none的標簽,然后再用選擇器取值)
	問題就出現在這里,因為賦值給標簽,之后再取值會發現格式亂掉了,該有的\r\n換行,都沒有了,所以就想辦法生成一個全局變量,用於存放上傳的文件(注意,上傳文件是在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="width: 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,
            )
'''
總結:
	此類問題可能出現在前端,也可能出現在后端,所以要想在最短的時間內定位出錯誤,就需要仔細分析(比如這個問題,源於文件大小的不同,但是只是有一點點不同,所以需要逆向思維,從數據庫查出數據后,再和前端傳來的數據作比較,這樣就能快速找到問題,是前端的問題了)
'''


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM