標籤:try app name 使用 required 關聯 lines sub print
網頁粘貼上傳
在做生產作業問答平台的時候,有一個功能需求是同意使用者在提問或回答時直接然後粘貼在編輯框中。然後提交。在開發前端時我使用的uikit,但uikit裡面的htmleditor外掛程式對圖片上傳支援太差,僅僅好放棄。又去看了其它網頁編輯控制項,但發現這些控制項處理圖片的方式都是選擇網路片或者從本地上傳的,這對發表文章部落格之類的還好。可是對於我所做的問答平台的使用者來說,他們很多其它的僅僅是直接簡短的闡述自己遇到的須要主管或他人解答的問題,對格式差點兒沒有要求。所以越簡單越方便越好。
參考知乎的做法。發現知乎是粘貼後馬上上傳圖片的,這樣做會存在一個問題。一旦使用者取消操作之後假設沒有在後台對已上傳的圖片資料做刪除的話將會產生不少垃圾資料,與其在後台做記錄,還不如把問題放到前端去解決簡單。所以利用html5的FormData自己想了一套解決方式:
- 當使用者粘貼時。將圖片資料和建立的img元素的src屬性儲存到兩個數組DatasArray和UrlsArray中,通過下標索引進行關聯。
- 使用者點擊提交時擷取使用者編輯的內容content,遍曆UrlsArray中每一元素src_url,若src_url在content中。則將content中的src_url替換成uploadfile_i, i表示src_url在UrlsArray中的索引。然後在FormData中加入(uploadfile_i。DatasArray[i])索引值對。
- 在後台儲存圖片資料DatasArray[i]後,路徑為url,將content中的uploadfile_i替換成url。
- 若是更新內容,則在後台更新資料前先記錄之前的圖片連結preurl,若preurl不在當前提交的content中則刪除該圖片。
前端代碼例如以下:
var imageDatas2upload = new Array();var imageUrls2Upload = new Array();/* 從剪下板讀取圖片資料,建立img元素附加到指定元素,並將圖片blob資料和img的src屬性儲存在數組中 */function ReadImgFromClipboard( clipboardData, containerId ){ var i = 0, items, item, types; if( clipboardData ){ items = clipboardData.items; if( !items ){ return; } // 擷取資料類型 item = items[0]; types = clipboardData.types || []; for( ; i < types.length; i++ ){ if( types[i] === ‘Files‘ ){ item = items[i]; break; } } // 推斷是否是圖片類型 if( item && item.kind === ‘file‘ && item.type.match(/^image\//i) ){ // 讀取二進位圖片資料 var blob = item.getAsFile(); if(blob){ var reader = new FileReader(); reader.onload = function(e){ // 附加img元素到指定元素 var img = new Image(); img.src = e.target.result; $("#"+containerId).append(img); // 儲存blob資料和src屬性值到數組 imageDatas2upload.push(blob); imageUrls2Upload.push(img.src); }; reader.readAsDataURL(blob); } } }}
function csl_newqes(title, detail, topics, callback){ var c = new FormData; c.append("via", "xhr2"); // 將img的src屬性值替換為預留位置,並向FormData中加入(預留位置,資料)索引值對 for(var i=0;i<imageUrls2Upload.length;i++){ if(detail.indexOf(imageUrls2Upload[i]) >= 0){ var filename = ‘upload_file_‘ + i; detail = detail.replace(imageUrls2Upload[i],filename); c.append(filename, imageDatas2upload[i],filename); } } c.append("detail", detail); // 清空資料 imageUrls2Upload = []; imageDatas2upload = []; if(topics instanceof Array){ topics = topics.join(); } c.append("topics", topics); c.append("title", title); var success_callback = callback || function(){}; $.ajax({ url : ‘/create-question/‘ , type : ‘POST‘, data : c, processData: false, // 告知jquery不要自己主動轉換資料 contentType: false, // 告知jquery不要設定Content-Type要求標頭 dataType : ‘json‘, success : function(data){ if(data.success){ success_callback(data); } else{ _alertErrorResponse(data.message); } }, error : function(xhr, ts){ var msg = ts + ‘ : ‘ + xhr.statusText; _alertErrorResponse(msg); } });}
Django後台代碼例如以下:
@login_requireddef create_question(request): result = {‘success‘:1, ‘message‘:‘‘, ‘qid‘:None} try: title = request.POST[‘title‘] detail = request.POST[‘detail‘] topics = request.POST[‘topics‘].split(‘,‘) #讀取圖片資料儲存,將圖片連結預留位置替換成真實連結 hs = Haystack(tags=(‘qimages‘,), root=settings.MEDIA_ROOT) for fn in request.FILES: img = request.FILES.get(fn, None) file_name = ‘%s.jpeg‘ % str(uuid.uuid1()) hs.save(file_name, img.read()) url = _qa_image_url_prefix + file_name detail = re.sub(re.compile(fn), url, detail) username = request.user.username qes = Question().setTitle(title).setDetail(detail).setAsker(username) for tid in topics: if tid and tid not in qes.topics: qes.topics.append(tid) result[‘qid‘] = qes.save() except Exception as ex: result[‘success‘] = 0 result[‘message‘] = ‘error: %s. ‘ % str(ex) return JsonResponse(result)
網頁粘貼上傳