Ant Design upload 組件快速配置使用七牛雲

在使用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

相關文章
相關標籤/搜索