標籤:dup orm idt and 技術分享 一個 lse size try
大檔案上傳服務
一、前端
[webuploader](http://fex.baidu.com/webuploader/ ‘‘webuploader‘‘)
二、後端
django 2.0.0
這裡只貼出核心的代碼:
前端的:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <!--引入CSS--><link rel="stylesheet" type="text/css" href="https://cdn.staticfile.org/webuploader/0.1.1/webuploader.css"><link rel="stylesheet" type="text/css" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.3/css/bootstrap.css"><!--引入JS--><script type="text/javascript" src="https://cdn.staticfile.org/jquery/3.3.1/jquery.js"></script><script type="text/javascript" src="https://cdn.staticfile.org/webuploader/0.1.1/webuploader.js"></script><script type="text/javascript" src="https://cdn.staticfile.org/twitter-bootstrap/4.1.3/js/bootstrap.js"></script></head><body><div id="uploader" class="wu-example"> <!--用來存放檔案資訊--> <div id="thelist" class="uploader-list"></div> <div class="btns"> <div id="picker">選擇檔案</div> <button id="ctlBtn" class="btn btn-default">開始上傳</button> </div> <div class="progress"> <!-- 進度條 --> <div class="progress-bar progress-bar-striped active" role="progressbar" style="width:0%;"></div> </div></div> <script type="text/javascript"> $(document).ready(function() { var task_id = WebUploader.Base.guid(); //產生task_id var uploader = WebUploader.create({ //建立上傳控制項 swf: ‘https://cdn.staticfile.org/webuploader/0.1.1/Uploader.swf‘, //swf位置,這個可能與flash有關 server: ‘/resource/files/upload/‘, //接收每一個分區的伺服器位址 pick: ‘#picker‘, //填上傳按鈕的id選取器值 auto: true, //選擇檔案後,是否自動上傳 chunked: true, //是否分區 chunkSize: 10 * 1024 * 1024, //每個分區的大小,這裡為10M chunkRetry: 3, //某分區若上傳失敗,重試次數 threads: 1, //線程數量,考慮到伺服器,這裡就選了1 duplicate: true, //分區是否自動去重 formData: { //每次上傳分區,一起攜帶的資料 task_id: task_id, }, }); uploader.on(‘startUpload‘, function() { //開始上傳時,調用該方法 $(‘.progress-bar‘).css(‘width‘, ‘0%‘); $(‘.progress-bar‘).text(‘0%‘); }); uploader.on(‘uploadProgress‘, function(file, percentage) { //一個分區上傳成功後,調用該方法 $(‘.progress-bar‘).css(‘width‘, percentage * 100 - 1 + ‘%‘); $(‘.progress-bar‘).text(Math.floor(percentage * 100 - 1) + ‘%‘); }); uploader.on(‘uploadSuccess‘, function(file) { //整個檔案的所有分區都上傳成功,調用該方法 //上傳的資訊(檔案唯一識別碼,檔案名稱) var data = {‘task_id‘: task_id, ‘filename‘: file.source[‘name‘] }; $.get(‘/resource/upload/complete/‘, data); //ajax攜帶data向該url發請求 $(‘.progress-bar‘).css(‘width‘, ‘100%‘); $(‘.progress-bar‘).text(‘上傳完成‘); }); uploader.on(‘uploadError‘, function(file) { //上傳過程中發生異常,調用該方法 $(‘.progress-bar‘).css(‘width‘, ‘100%‘); $(‘.progress-bar‘).text(‘上傳失敗‘); }); uploader.on(‘uploadComplete‘, function(file) {//上傳結束,無論檔案最終是否上傳成功,該方法都會被調用 $(‘.progress-bar‘).removeClass(‘active progress-bar-striped‘); }); }); </script></body></html>
後端的:
路由
path(‘files/upload/‘, views.fileupload,name=‘圖片分區上傳‘), path(‘upload/complete/‘, views.fileMerge,name=‘上傳成功合并‘),
視圖:
@csrf_exemptdef fileupload(request): if request.method == ‘POST‘: upload_file = request.FILES.get(‘file‘) task = request.POST.get(‘task_id‘) # 擷取檔案唯一識別碼 chunk = request.POST.get(‘chunk‘, 0) # 擷取該分區在所有分區中的序號 filename = ‘%s%s‘ % (task, chunk) # 構成該分區唯一識別碼 print("filename=",filename) default_storage.save(‘./upload/%s‘ % filename,ContentFile(upload_file.read())) # 儲存分區到本地 return render_to_response(‘upload.html‘,locals())@csrf_exemptdef fileMerge(request): print(request.GET) task = request.GET.get(‘task_id‘) ext = request.GET.get(‘filename‘, ‘‘) upload_type = request.GET.get(‘type‘) if len(ext) == 0 and upload_type: ext = upload_type.split(‘/‘)[1] ext = ‘‘ if len(ext) == 0 else ‘.%s‘ % ext # 構建檔案尾碼名 chunk = 0 with open(‘./upload/%s%s‘ % (task, ext), ‘wb‘) as target_file: # 建立新檔案 while True: try: filename = ‘./upload/%s%d‘ % (task, chunk) source_file = open(filename, ‘rb‘) # 按序開啟每個分區 target_file.write(source_file.read()) # 讀取分區內容寫入新檔案 source_file.close() except IOError: break chunk += 1 os.remove(filename) # 刪除該分區,節約空間 return render_to_response(‘upload.html‘,locals())
:
django+python大檔案上傳