在使用ant design
開發後臺業務過程當中,遇到了給upload
組件配置後臺服務器的問題。由於用習慣了七牛雲的快速易用,以及喜歡它的自動壓縮接口,所以第一反應就是想怎麼配置上傳到七牛雲上面。
不過通過多番搜尋,並沒找到好的解決方案。官方推薦參考的jQuery-File-Upload服務端上傳接口實現測試了幾個nodejs
的實現,發現好久沒有維護了,存在一些問題。因而只能從閱讀ant design
源代碼來看能不能怎麼修改upload
的上傳方式,從而實現提交圖片過去。javascript
首先從ant design的upload組件源碼能夠看到,它是基於這個upload組件編寫的。再看該upload組件,獲得具體的request實現:html
function getError(option, xhr) { const msg = `cannot post ${option.action} ${xhr.status}'`; const err = new Error(msg); err.status = xhr.status; err.method = 'post'; err.url = option.action; return err; } function getBody(xhr) { const text = xhr.responseText || xhr.response; if (!text) { return text; } try { return JSON.parse(text); } catch (e) { return text; } } // option { // onProgress: (event: { percent: number }): void, // onError: (event: Error, body?: Object): void, // onSuccess: (body: Object): void, // data: Object, // filename: String, // file: File, // withCredentials: Boolean, // action: String, // headers: Object, // } export default function upload(option) { const xhr = new XMLHttpRequest(); if (option.onProgress && xhr.upload) { xhr.upload.onprogress = function progress(e) { if (e.total > 0) { e.percent = e.loaded / e.total * 100; } option.onProgress(e); }; } const formData = new FormData(); if (option.data) { Object.keys(option.data).map(key => { formData.append(key, option.data[key]); }); } formData.append(option.filename, option.file); xhr.onerror = function error(e) { option.onError(e); }; xhr.onload = function onload() { // allow success when 2xx status // see https://github.com/react-component/upload/issues/34 if (xhr.status < 200 || xhr.status >= 300) { return option.onError(getError(option, xhr), getBody(xhr)); } option.onSuccess(getBody(xhr), xhr); }; xhr.open('post', option.action, true); // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179 if (option.withCredentials && 'withCredentials' in xhr) { xhr.withCredentials = true; } const headers = option.headers || {}; // when set headers['X-Requested-With'] = null , can close default XHR header // see https://github.com/react-component/upload/issues/33 if (headers['X-Requested-With'] !== null) { xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); } for (const h in headers) { if (headers.hasOwnProperty(h) && headers[h] !== null) { xhr.setRequestHeader(h, headers[h]); } } xhr.send(formData); return { abort() { xhr.abort(); }, }; }
至此上傳的邏輯一目瞭然,那麼能夠怎麼改造呢?再翻閱一下七牛雲的文檔,獲得一個利用js上傳的實現:java
/* * 本示例演示七牛雲存儲表單上傳 * * 按照如下的步驟運行示例: * * 1. 填寫token。須要您不知道如何生成token,能夠點擊右側的連接生成,而後將結果複製粘貼過來。 * 2. 填寫key。若是您在生成token的過程當中指定了key,則將其輸入至此。不然留空。 * 3. 姓名是一個自定義的變量,若是生成token的過程當中指定了returnUrl和returnBody, * 而且returnBody中指定了指望返回此字段,則七牛會將其返回給returnUrl對應的業務服務器。 * callbackBody亦然。 * 4. 選擇任意一張照片,而後點擊提交便可 * * 實際開發中,您能夠經過後端開發語言動態生成這個表單,將token的hidden屬性設置爲true並對其進行賦值。 * * ********************************************************************************** * * 貢獻代碼: * * 1. git clone git@github.com:icattlecoder/jsfiddle * * 2. push代碼到您的github庫 * * 3. 測試效果,訪問 http://jsfiddle.net/gh/get/jquery/1.9.1/<Your GitHub Name>/jsfiddle/tree/master/ajaxupload * * 4. 提pr * ********************************************************************************** */ $(document).ready(function() { var Qiniu_UploadUrl = "http://up.qiniu.com"; var progressbar = $("#progressbar"), progressLabel = $(".progress-label"); progressbar.progressbar({ value: false, change: function() { progressLabel.text(progressbar.progressbar("value") + "%"); }, complete: function() { progressLabel.text("Complete!"); } }); $("#btn_upload").click(function() { //普通上傳 var Qiniu_upload = function(f, token, key) { var xhr = new XMLHttpRequest(); xhr.open('POST', Qiniu_UploadUrl, true); var formData, startDate; formData = new FormData(); if (key !== null && key !== undefined) formData.append('key', key); formData.append('token', token); formData.append('file', f); var taking; xhr.upload.addEventListener("progress", function(evt) { if (evt.lengthComputable) { var nowDate = new Date().getTime(); taking = nowDate - startDate; var x = (evt.loaded) / 1024; var y = taking / 1000; var uploadSpeed = (x / y); var formatSpeed; if (uploadSpeed > 1024) { formatSpeed = (uploadSpeed / 1024).toFixed(2) + "Mb\/s"; } else { formatSpeed = uploadSpeed.toFixed(2) + "Kb\/s"; } var percentComplete = Math.round(evt.loaded * 100 / evt.total); progressbar.progressbar("value", percentComplete); // console && console.log(percentComplete, ",", formatSpeed); } }, false); xhr.onreadystatechange = function(response) { if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText != "") { var blkRet = JSON.parse(xhr.responseText); console && console.log(blkRet); $("#dialog").html(xhr.responseText).dialog(); } else if (xhr.status != 200 && xhr.responseText) { } }; startDate = new Date().getTime(); $("#progressbar").show(); xhr.send(formData); }; var token = $("#token").val(); if ($("#file")[0].files.length > 0 && token != "") { Qiniu_upload($("#file")[0].files[0], token, $("#key").val()); } else { console && console.log("form input error"); } }) })
經過審閱其中的核心邏輯能夠知道,*它的上傳邏輯與antd 的upload組件的核心區別就是formData
增長了七牛雲上傳token:node
formData.append('token', token);
而經過upload的request源碼又能夠知道,能夠經過option.data傳過來的參數執行formData.append('token', token);
,該部分的源碼以下:react
const formData = new FormData(); if (option.data) { Object.keys(option.data).map(key => { formData.append(key, option.data[key]); }); }
由此,再參閱ant design官方文檔能夠知道,使用Upload
組件時,能夠經過data API傳入自定義的data,那麼自此就能夠獲得一個簡潔的辦法,經過如下sample code就能夠實現Upload
組件上傳圖片到七牛雲:jquery
const QINIU_SERVER = 'http://up.qiniu.com' data = { token: 'PUT-YOUR-TOKEN-HERE', } <Upload action={QINIU_SERVER} listType="picture-card" className="upload-list-inline" onChange={this.onChange} onPreview={this.handlePreview} fileList={fileList} data={this.data} > {uploadButton} </Upload>
最後劃重點:git
BTW, 若是使用的是七牛雲其餘地區如華南地區的Bucket,須要替換使用其餘地區的上傳域名進action,具體可參考這裏。Enjoy it!
github