ant design Upload組件的使用總結


事先說明:upload 所使用"rc-upload"組件在npm是有單獨的包,upload對其進一步封裝。"rc-upload"

有更多的API選擇。

需求

要求限制上傳圖片的格式、大小、分辨率。

簡單介紹

這是一個最簡單的upload組件使用

<Upload action="...">
    上傳
</Upload>

簡單說一下關鍵幾個參數

參數 作用
action 上傳的服務器地址,使用默認上傳行為必填
beforeUpload 默認上傳行為之前的鈎子函數,用來限制上傳文件
customRequest 自定義上傳(本文關鍵)
fileList 已上傳列表

本文的關鍵就在於customRequest、fileList和onRemove三個api。

平常使用

該組件已經將上傳文件封裝的及其簡單

<Upload action="..." onChange={...} beforeUpload={...}>
    上傳
</Upload>

在所有提供的鈎子函數都會接受file參數。它就是用戶上傳文件的RcFile形式。

主要參數有

{
   type    	// 文件格式
   size     // 文件大小
   status 	// 狀態有:uploading done error removed 只有在onChange事件才會變化
   response // 服務端響應內容,
}

在beforeUpload調用file的type和size來限制上傳文件。beforeUpload如果返回false就是取消上傳行為。

來至官網的示例

function beforeUpload(file) {
  const isJPG = file.type === 'image/jpeg';
  if (!isJPG) {
    message.error('You can only upload JPG file!');
  }
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isLt2M) {
    message.error('Image must smaller than 2MB!');
  }
  return isJPG && isLt2M;
}

當文件開始上傳的時候,這時候調用onChange 讀取到file.response獲取到服務端的回調,來實現我們的功能。

進一步使用

  1. 顯然默認的行為不能實現我的要求,file對象並沒有分辨率的參數。我所采用的是把上傳的圖片實例化讀取它的高寬。這樣出現一個問題。image只有在觸發load事件之后才能被讀取寬高,我們沒有辦法將我們的判斷傳遞給beforeUpload,也就阻止不了上傳事件。
const { file } = files
// files是customRequest參數
const reader = new FileReader();
    reader.addEventListener("load", e => {
      const data = e.target.result;
      //加載圖片獲取圖片真實寬度和高度
      const image = new Image();
      image.addEventListener("load", () => {
        const w = image.width;
        const h = image.height;
      });
      image.src = data;
    });
 reader.readAsDataURL(file);
// 我們傳遞不出false。

所有只能使用customRequest來覆蓋默認上傳。但這樣有兩個弊端。

  1. 上傳狀態無法被onChange捕獲。

  2. 我們需要自己控制fileList。

  3. 組件showUploadList會出現我們不想展示的圖片。

其實到這一步已經可以實現效果,但是我想要組件的showUploadList所展示的上傳列表,畢竟別人已經寫好動畫了。

所有我們要控制fileList於state綁定,初始值設為[],上傳成功后fileList增加新的元素。

customRequest = (files) => {
    const { file } = files
    ...// 前面限制
    let formData = new FormData();
    formData.append("file", file);
    http('',formData).then(
   	   res =>
    	this.setState(() => ({ fileList: [{ ...file }, { url, status: "done" }] }));
    )
}

設置的fileList是安裝官方defaultFileList 的形式添加的

{
    uid: '1',
    name: 'xxx.png',
    status: 'done',
    response: 'Server Error 500', // custom error message to show
    url: 'http://www.baidu.com/xxx.png',
  }

onRemove

使用了showUploadList就需要使用onRemove來刪除文件列表元素。我們先看看onRemove的介紹

點擊移除文件時的回調,返回值為 false 時不移除。支持返回一個 Promise 對象,Promise 對象 resolve(false) 或 reject 時不移除

由於同時涉及到表單我也用了Form組件,同樣也要使用Form組件的表單驗證。

onRemove = () => {
	this.setState(() => ({
		fileList: []
  }));
}

圖片是刪除里但是並沒有觸發Form的驗證。Form都是靠表單的onChange來觸發的。所有查了一下源碼。

handleRemove(file: UploadFile) {
    const { onRemove } = this.props;
    Promise.resolve(typeof onRemove === 'function' ? onRemove(file) : onRemove).then(ret => {
      // Prevent removing file
      if (ret === false) {
        return;
      }

      const removedFileList = removeFileItem(file, this.state.fileList);
      if (removedFileList) {
        this.onChange({
          file,
          fileList: removedFileList,
        });
      }
    });
  }

其中的 removeFileItem 如下

export function removeFileItem(file: UploadFile, fileList: UploadFile[]) {
  const matchKey = file.uid !== undefined ? 'uid' : 'name';
  const removed = fileList.filter(item => item[matchKey] !== file[matchKey]);
  if (removed.length === fileList.length) {
    return null;
  }
  return removed;
}

可以看出之前fileList已被我們設為[],removeFileItem 返回為null,所以沒有觸發onChange。沒辦法,我們只能自己觸發了,傳入參數上面的代碼已給出。

<Upload ref=ref => this.ref = ref>
    上傳
</Upload>

onRemove = () => {
	...// 前面操作
    this.ref.onChange({file,[]})
}

至此我個人所有需求全部解決。但是我在逛github的Issues 的時候發現有人提這樣無法獲取上傳的進度。

ajax是有原生獲取上傳文件進度的方法的。我使用的是axios的onUploadProgress方法。

 onUploadProgress:(progressEvent) => { 
    const {lengthComputable, loaded, total} = progressEvent 
    lengthComputable, //是否能夠被讀取長度
    loaded// 已上傳,
    total //以下載    
 },


免責聲明!

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



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