精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

關于 Ant Design 上傳組件 <Upload> 的入門教程

開發 前端
本文我們循序漸進地講解了 Ant Design 中 <Upload> 上傳組件的用法。涵蓋基礎用法、簡單上傳服務地編寫以及 uploadProps 的核心 prop 的定義和使用。

Ant Design[1] 是螞蟻集團開源的一款 React UI 庫。UI 庫內置了很多開箱即用的組件,特別適應于開發公司內部網頁,當然由于其出色的交互和強大能力,也有一些公司選擇它直接用于構建對外的客戶端網頁。

在之前的一篇文章中,我們介紹了 Ant Design 中關于動態表單的構建教程[2]。本文,我們將繼續探索另一個常見使用場景——文件上傳組件 <Upload> 的應用。

圖片圖片

<Upload> 初印象

我們先從 <Upload> 基礎功能講起。如下所示:

import { Upload, Button } from 'antd'

function Example() {
  return (
    <div>
      <Upload>
        <Button>click to upload</Button>
      </Upload >
    </div>
  )
}

<Upload> 組件本身提供了上傳能力,至于上傳能力的觸發,則有賴于其 children 內容。<Upload> 組件的 children 內容我們完全可以自定義,本案例場景,我們簡單放入一個按鈕即可。

展示效果如下:

圖片圖片

點擊"click to upload"按鈕,就能觸發文件彈窗的出現。

我們可以通過控制臺查看最終生成的 DOM 結構:

圖片圖片

發現,在渲染出來的 <Button> 組件的上方,有一個 display: none 的 <input type="file">!所以其觸發機制是:在點擊 <Button> 組件時,antd 內部會關聯到 <input type="file"> 的點擊,于是便彈出一個文件上傳對話框。

使用 <Upload> 時報錯了

如果我們只寫了上面的代碼,并嘗試點擊“打開”上傳文件時,會看到報錯。

圖片圖片

這是因為我們沒有指定文件上傳服務。默認 <Upload> 使用當前 URL 作為文件上傳地址。

圖片圖片

也能看到,在文件上傳時,請求的內容類型 Content-Type 是 multipart/form-data,在上傳文件時,也必然要使用這種請求類型。

現在,因為我們并沒實現該請求類型的文件上傳服務,自然就報錯了。

接下來,我們著手實現一個文件上傳服務。

實現一個簡單的文件上傳服務

首先,安裝依賴。

npm install express formidable cors

express 作為我們的后端路由服務器;formidable 則是一個 Node.js 模塊,用于解析表單數據,尤其是文件上傳場景;cors 則是讓我們的服務開放跨域請求的能力。

我們的服務端代碼實現如下:

// server/app.js
import express from 'express';
import cors from 'cors';
import formidable from 'formidable';

const app = express();

app.use(cors()); // Enable CORS for all routes

// Serve static files from the 'uploads' directory
app.use('/uploads', express.static('uploads'));

app.get('/', (req, res) => {
  res.send(`
    <h2>With <code>"express"</code> npm package</h2>
    <form actinotallow="/api/upload" enctype="multipart/form-data" method="post">
      <div>Text field title: <input type="text" name="title" /></div>
      <div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
      <input type="submit" value="Upload" />
    </form>
  `);
});

app.post('/api/upload', (req, res, next) => {
  const form = formidable({});

  form.parse(req, (err, fields, files) => {
    if (err) {
      next(err);
      return;
    }
    res.json({ fields, files });
  });
});

app.listen(3000, () => {
  console.log('Server listening on http://localhost:3000 ...');
});

總體代碼量并不多:

  1. 首先,根路由(/)返回了一端 HTML 用于測試文件上傳能力
  2. 其次,文件上傳的服務路由是 POST /api/upload,在這個版本的實現上,我們只是先簡單打印出來提交的表單內容

下面啟動服務:

node --watch .\server\app.js

瀏覽器訪問:http://localhost:3000/,就能看到一個簡陋的文件上傳測試頁。

圖片圖片

我們點擊選中 2 個文件進行上傳,結果就能看到 /api/upload 的返回結果。

圖片圖片

files 代表文件表單域,fields 則代表非文件表單域。接著,我們替換掉 res.json({ fields, files }) 的內容。

res.json({ fields, files });

替換為:

const oldpath = files.someExpressFiles[0].filepath;
const originalFilename = files.someExpressFiles[0].originalFilename;
const extension = path.extname(originalFilename);

const today = new Date();
const year = today.getFullYear();
const month = ('0' + (today.getMonth() + 1)).slice(-2); // pad with leading zero if necessary
const newFilename = `${year}/${month}/${originalFilename.replace(extension, '')}-${Date.now()}${extension}`;
const newpath = path.join('uploads', newFilename);

fs.cp(oldpath, newpath, (err) => {
  if (err) {
    res.writeHead(500, { 'Content-Type': 'text/plain' });
    res.end('Error moving file');
    return;
  }

  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end(JSON.stringify({
    message: 'File uploaded successfully',
    path: newpath,
  }));
});

目的也比較簡單,就是把上傳的文件存儲到本地硬盤。存儲位置位于 uploads/[year]/[month] 目錄之下。在此之前,我們已經將 uploads 目錄設置為可靜態訪問了。

// Serve static files from the 'uploads' directory
app.use('/uploads', express.static('uploads'));

現在,在此點擊上傳文件。

圖片圖片

展示上傳成功。

圖片圖片

這個時候,我們就會在項目中看到 uploads/ 目錄下已經有剛才上傳的文件了。

圖片圖片

這樣,我們就實現了一個簡單的文件上傳服務。下面,就可以讓 <Upload> 來接入了。

Upload 接入 /api/upload

<Upload> 接入上傳服務,是通過指定 props 實現的。

function Example() {
  const props = {
    action: 'http://localhost:3000/api/upload',
    name: 'someExpressFiles',
    onChange(info) {
      if (info.file.status !== 'uploading') {
        console.log(info.file, info.fileList);
      }
      if (info.file.status === 'done') {
        message.success(`${info.file.name} file uploaded successfully`);
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
  };

  return (
    <div>
      <Upload {...props}>
        <Button>click to upload</Button>
      </Upload >
    </div>
  )
}

在上傳場景中,name、action 和 onChange 是 3 個被廣泛使用的 prop。

  • action:這是核心。用于指定上傳文件的服務路徑。也就是我們前一步實現的 /api/upload
  • name:上傳文件時,后端服務獲取文件信息的表單字段名
  • onChange:用于觀察上傳結果。上傳成功或失敗都會觸發

下面,我們再試一下文件上傳。

圖片圖片

提示文件被成功上傳了!

在控制臺中,我們還能看到打印出來的響應內容。

圖片圖片

onChange 回調函數的 info 參數中,包含 2 個屬性: file 和 fileList。file 指代當前上傳的文件;fileList 則代表當前 <Upload> 組件中已有/還剩下的文件列表。

你可以通過 file.response 獲得服務端的響應數據,同時可以通過 originFileObj 屬性獲得上傳文件的原始信息。

與 <Form> 組件配合使用

當然,在實際的業務場景中,在文件上傳之后流程并未結束,我們通常還需要將服務端返回的圖片路徑跟隨其他表單字段一起保存起來,比如更新個人中心里的頭像這類場景。

這個時候 <Upload> 就要搭配 <Form> 一起使用了。

以下面的 DEMO 為例:

function Example() {
  const [form] = Form.useForm();

  const props = {
    name: 'someExpressFiles',
    listType: "picture-card",
    action: 'http://localhost:3000/api/upload',
  };

  const onFinish = (values) => {
    console.log('Submit values:', values);
    // 發送表單數據到后端
  };

  return (
    <div>
      <Form form={form} onFinish={onFinish}>
        <Form.Item
          name="name"
          rules={[{ required: true, message: '請輸入姓名' }]}
        >
          <Input placeholder="姓名" />
        </Form.Item>
        <Form.Item
          name="avatar"
          rules={[{ required: true, message: '請選擇頭像' }]}
        >
          <Upload {...props}>
            上傳文件
          </Upload >
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit">
            提交
          </Button>
        </Form.Item>
      </Form>

    </div>
  )
}

本例中為 uploadProps 增加了 listType: "picture-card" 配置,這樣在上傳完圖片后,可以小圖預覽。

選擇文件,點擊上傳:

圖片圖片

點擊“提交”,控制臺便能看到打印出來的表單數據了。

圖片圖片

可以看到,最近一次的 onChang 事件里的內容,會作為數據在提交表單時使用。

另外,uploadProps 還提供了 fileList prop 參數用來手動控制預覽文件列表的展示行為,比如我們只想查看最近兩次的圖片預覽,就可以這樣做:

const [fileList, setFileList] = useState([]);

const props = {
  name: 'someExpressFiles',
  listType: "picture-card",
  fileList,
  action: 'http://localhost:3000/api/upload',
  onChange({ file, fileList: newFileList }) {
    setFileList(newFileList.slice(-2));
  },
};

如此依賴,上傳的文件始終展示最新上傳的 2 張,之前舊的就會被剔除。

福利內容:Ctrl + V 上傳文件

Ant Design 的 <Upload> 并未直接提供粘貼上傳文件的支持。這個時候就要通過 ref 操作其實例來實現了。

首先,uploadProps 增加 ref 支持,這樣我們就能訪問到 <Upload> 的底層實例對象了。

const props = {
  ref: uploadRef,
  // ...
};

<Form.Item
  name="file"
  rules={[{ required: true, message: '請選擇文件' }]}
>
  <Upload {...props}>
    上傳文件
  </Upload >
</Form.Item>

接著為要支持粘貼上傳的文本框綁定 onPaste 事件,提供粘貼行為的監聽。

<textarea
  notallow={handlePaste}
  placeholder="粘貼文件到此處"
/>

在處理函數內部像下面這樣寫。

const handlePaste = (e) => {
  e.preventDefault();
  // 1)
  const files = e.clipboardData.files;

  if (files.length > 0) {
    const file = files[0];
    if (uploadRef.current) {
      // 2)
      uploadRef.current.upload.uploader.onChange({ target: { files: [file] } }); // 手動觸發 Upload 組件的上傳操作
    }
  }
};
  1. 首先,獲取獲取剪貼板上的文件(只取第一個)
  2. 手動調用 uploadRef.current.upload.uploader.onChange() 方法,傳入手動拼湊的事件對象 { target: { files: [file] } } 即可。

注意,這種上傳能力是我自己摸索出來的,并不是官方做法。最好是作為漸進功能使用。

總結

本文我們循序漸進地講解了 Ant Design 中 <Upload> 上傳組件的用法。涵蓋基礎用法、簡單上傳服務地編寫以及 uploadProps 的核心 prop 的定義和使用。

責任編輯:武曉燕 來源: 寫代碼的寶哥
相關推薦

2024-10-29 08:57:25

2010-03-12 14:26:58

Python入門教程

2025-08-28 06:20:00

2024-11-12 15:46:37

2009-07-08 15:12:48

Java Servle

2014-05-26 15:35:55

Web組件Web Compone

2013-08-29 14:12:52

Storm分布式實時計算

2010-08-03 13:06:15

Flex Builde

2022-07-12 08:27:18

Zadig開源

2022-07-21 11:58:12

Docker

2010-03-12 14:04:32

Python入門教程

2013-06-24 13:38:34

HTML5 DataList

2018-03-22 14:59:13

Docker入門容器

2010-06-18 16:56:50

UML建模語言

2011-09-02 10:59:10

jQuery Mobi

2010-07-20 16:19:54

Perl

2010-06-13 09:45:35

Widget開發

2011-07-21 10:29:18

iPhone 開發

2010-07-27 15:53:15

2013-08-29 14:28:09

StormHadoop
點贊
收藏

51CTO技術棧公眾號

久久综合九色综合欧美就去吻| 欧美中文一区二区| 亚洲超碰97人人做人人爱| 91日韩久久| 久久露脸国语精品国产91| 亚洲春色h网| 欧美精品在线视频| 中文字幕无码精品亚洲资源网久久| 深夜福利视频在线免费观看| 青青草伊人久久| 欧美日韩成人在线播放| 亚洲人成人无码网www国产| 亚洲我射av| 狠狠躁夜夜躁人人躁婷婷91| 亚洲国产一区二区在线| 成人av无码一区二区三区| 久久国产主播| 久久99精品久久久久久噜噜| 先锋影音av在线| 粉嫩av一区二区| 欧美日韩国产精选| 波多野结衣家庭教师在线播放| 欧美精品电影| 久久尤物电影视频在线观看| 成人黄色网免费| 日本va欧美va国产激情| 国产精品香蕉| 欧美日韩亚洲高清一区二区| 国产婷婷一区二区三区| www.久久热.com| 成人中文字幕在线| 国产精品色视频| 精品无码人妻一区二区三区品 | 亚洲成人黄色片| 尤物精品在线| www.精品av.com| 日本少妇色视频| www.久久99| 日本精品视频一区二区| 国产精品一线二线三线| 久久国产精品一区| 久久久久久9999| 国产高清一区二区三区| 一级黄色片在线看| 欧美一级二区| 久久久久久九九九| 香蕉久久久久久久| 亚洲精品一级二级三级| 精品国产亚洲一区二区三区在线观看| 丁香婷婷激情网| 阿v视频在线| 伊人开心综合网| 一本一本a久久| 国模吧精品人体gogo| 国产成人免费网站| 91亚洲va在线va天堂va国| 国产精品无码一区| 久久天堂精品| 欧美一级淫片videoshd| 人妻人人澡人人添人人爽| 免费视频一区三区| 精品国产免费视频| 少妇愉情理伦片bd| 日韩亚洲精品在线观看| 日韩一区二区在线观看| 日韩成人av免费| 国产在线视频欧美一区| 538prom精品视频线放| the porn av| 国产激情久久| 欧美人狂配大交3d怪物一区| 黄色永久免费网站| 国产精品久久久久77777丨| 色婷婷综合激情| 国产肥臀一区二区福利视频| 在线最新版中文在线| 精品久久中文字幕久久av| 免费一级特黄毛片| 51精品视频| 五月综合激情婷婷六月色窝| 美女在线免费视频| 在线免费观看a视频| 一区二区在线电影| 性高湖久久久久久久久aaaaa| 欧美aaaxxxx做受视频| 一区二区三区四区在线播放| 亚洲国产一二三精品无码| 色www永久免费视频首页在线| 亚洲综合激情网| 国产欧美日韩网站| 日本在线啊啊| 在线区一区二视频| 亚洲美女性囗交| 麻豆国产一区| 亚洲精品一区二区三区精华液| 久久国产劲爆∧v内射| 日韩精品亚洲aⅴ在线影院| 精品视频久久久久久久| 欧美黄色一级生活片| 日韩精品午夜| 欧美俄罗斯性视频| 欧美啪啪小视频| 久久精品国产99国产精品| 亚洲自拍偷拍福利| 五月婷婷六月色| 国产欧美视频一区二区| 日韩精品久久一区二区三区| 欧美猛烈性xbxbxbxb| 亚洲三级在线免费| 欧美 激情 在线| 91国产一区| 亚洲精品按摩视频| 美女福利视频网| 一区二区蜜桃| 国产成人精彩在线视频九色| 中文字幕一区二区人妻| 国产 欧美在线| 欧美日韩综合久久| 91一区二区三区在线| 欧美日韩在线影院| 国内av一区二区| 免费成人网www| 色噜噜狠狠狠综合曰曰曰| 免费一级全黄少妇性色生活片| 国产美女诱惑一区二区| 国产一区二中文字幕在线看| 人妻少妇精品无码专区| 国产精品久久久久永久免费观看| 日本中文字幕在线视频观看 | 国产日韩欧美91| 免费国产羞羞网站视频| 国产精品―色哟哟| 777精品久无码人妻蜜桃| 亚洲免费一区| 亚洲欧洲av一区二区| 三级黄色片在线观看| 亚洲伊人观看| yy111111少妇影院日韩夜片| av电影在线网| 日韩欧美在线视频免费观看| 人妻巨大乳一二三区| 久久综合亚洲| 国内精品久久久久久久久| 国产又粗又猛又色又| 99久久精品久久久久久清纯| 影音先锋男人的网站| 性爽视频在线| 亚洲国产精品免费| 妺妺窝人体色www在线下载| 免费成人美女在线观看.| 六十路精品视频| 超免费在线视频| 制服丝袜日韩国产| 亚洲色图日韩精品| 日韩电影一二三区| 欧美重口乱码一区二区| 69xxx在线| 欧美久久久久中文字幕| 大胸美女被爆操| 三级欧美在线一区| 美女黄毛**国产精品啪啪| 高清在线视频不卡| 精品国产在天天线2019| 欧美日韩三级在线观看| 国产一区视频导航| 桥本有菜av在线| 色综合视频一区二区三区44| 色悠悠国产精品| 这里只有精品国产| 中文字幕国产精品一区二区| 日韩在线第三页| 日韩精品一区二区三区免费观看| 国产成人精品综合| 超碰97在线免费观看| 欧美视频三区在线播放| 人妻少妇无码精品视频区| 久久不射中文字幕| 欧美日韩在线精品一区二区三区| 日韩中文影院| 国产视频亚洲精品| 国产专区第一页| 91欧美一区二区| 9久久婷婷国产综合精品性色| 欧美日中文字幕| 国产视频999| 青青在线视频| 日韩成人av一区| 中文字幕av第一页| 日韩一区在线看| 久久久无码人妻精品无码| 国产欧美日韩一区二区三区在线| 免费观看成人高| 久久91视频| 欧美人与物videos| 视频午夜在线| 欧美四级电影网| 欧美日韩一级大片| 91免费小视频| 熟妇人妻va精品中文字幕| 国产精品片aa在线观看| 国产成人精品一区二区在线| 欧美私人网站| 日韩黄在线观看| 亚洲一区二区激情| 亚洲国产精品嫩草影院| 91国模少妇一区二区三区| 久久国产尿小便嘘嘘| 99色这里只有精品| 欧美日韩亚洲在线观看| 成人动漫视频在线观看免费| av日韩电影| 久久夜色精品国产| 天堂中文在线视频| 91精品国产综合久久精品麻豆| 国产女同在线观看| 一区在线播放视频| 久久国产免费视频| 久久精品国产亚洲a| 黄色一级在线视频| 欧美好骚综合网| 精品欧美日韩| 免费一级欧美在线大片| 国产成人一区二| 成人超碰在线| 精品国产一区二区三区久久久| 午夜在线视频免费| 欧美一区二区在线看| 亚洲自拍一区在线观看| 亚洲午夜羞羞片| 久久av红桃一区二区禁漫| 91蜜桃视频在线| 91精品人妻一区二区三区蜜桃2 | 国产视频手机在线播放| 亚洲激情影院| 国风产精品一区二区| 欧美限制电影| 欧美男人的天堂| 99精品在免费线中文字幕网站一区| 国产精品久久久久久亚洲调教| 欧美78videosex性欧美| 日韩天堂在线视频| 黄色视屏网站在线免费观看| 亚洲成人激情在线| 精品国产乱码一区二区三| 欧美日韩在线播放三区四区| 国产成人在线视频观看| 亚洲图片欧美视频| 欧美成人免费观看视频| 中文字幕日韩精品一区 | 中文精品久久久久人妻不卡| 激情亚洲一区二区三区四区 | 少妇丰满尤物大尺度写真| 久久精品国产精品亚洲精品| 日本va中文字幕| 美女久久网站| 熟女性饥渴一区二区三区| 国产视频欧美| 日本一区二区黄色| 国产精品毛片一区二区三区| 一本久道高清无码视频| 欧美涩涩网站| 一区二区三区观看| 波多野结衣在线观看一区二区 | 欧美日中文字幕| 亚洲成色www久久网站| 欧美视频网址| 一道精品一区二区三区 | 椎名由奈jux491在线播放 | 蜜臀精品久久久久久蜜臀| 免费看黄色一级大片| 日韩国产精品91| 99热这里只有精品在线播放| 美国三级日本三级久久99| 日韩毛片在线免费看| 日本女人一区二区三区| www国产黄色| 麻豆久久一区二区| 日本国产一级片| 国产美女娇喘av呻吟久久| 午夜诱惑痒痒网| 国产91对白在线观看九色| 国产一级免费片| 91小视频免费看| 色一情一交一乱一区二区三区 | 欧美国产一区二区在线| 欧美人与牛zoz0性行为| 亚洲国产激情一区二区三区| 国产精品久久天天影视| 国产成人亚洲综合无码| 亚洲黄色av| 50路60路老熟妇啪啪| 美国欧美日韩国产在线播放| 999久久久精品视频| 成人综合婷婷国产精品久久蜜臀 | 亚洲新声在线观看| 成人在线观看免费网站| 高清欧美性猛交| 天然素人一区二区视频| 成人性生交xxxxx网站| 粉嫩一区二区三区四区公司1| 欧美日本国产精品| 国产精品99一区二区三| 日韩 欧美 视频| 日韩极品在线观看| 国产调教打屁股xxxx网站| 97久久超碰国产精品电影| 国产一区二区三区视频播放| 夜夜嗨av一区二区三区网页| www.色国产| 日韩免费看网站| 国产资源在线播放| 欧美老女人性生活| av日韩亚洲| 999视频在线观看| 国产精品美女久久久久久不卡| 日韩不卡一二区| 视频一区国产视频| gogo亚洲国模私拍人体| 久久蜜桃av一区二区天堂 | 中国老熟女重囗味hdxx| 国产午夜精品一区二区| 免费视频一二三区| 欧美日韩亚洲综合| 男人天堂网在线观看| 欧美大胆a视频| 91欧美精品| 久久青青草原一区二区| 97精品一区二区| 国产免费毛卡片| 99在线视频精品| 国产免费无码一区二区视频 | 亚洲视频久久久| 日韩精品视频免费| 欧美性爽视频| 成人精品一区二区三区| 欧美一区二区三| 色综合av综合无码综合网站| 福利一区二区在线| 69夜色精品国产69乱| 欧美亚洲一区二区在线| 香蕉av在线播放| 欧美国产精品日韩| 二区三区精品| 亚洲一区二区三区免费看| 一区二区三区福利| 俄罗斯女人裸体性做爰| 国产精品久久久久aaaa| 国产成人精品一区二区色戒| 亚洲男人天堂古典| 国产精品一二三产区| 春色成人在线视频| 欧美精品一卡| 欧美色图校园春色| 亚洲美女屁股眼交| 99久久久国产精品无码网爆| 日韩亚洲一区二区| 色婷婷成人网| 一区二区在线观看网站| 麻豆成人免费电影| 成人黄色短视频| 337p亚洲精品色噜噜狠狠| 久久精品视频免费看 | 6080成人| 免费网站在线观看视频| 国产精品69毛片高清亚洲| 91在线播放观看| 日韩精品在线看片z| 丝袜在线观看| 国产区一区二区三区| 亚洲九九精品| 欧产日产国产精品98| 精品成人国产在线观看男人呻吟| 五月婷婷免费视频| 国产成人精品免费久久久久 | 91精品婷婷国产综合久久| 韩国中文字幕在线| 91黄在线观看| 亚洲福利免费| 国产呦小j女精品视频| 色噜噜狠狠一区二区三区果冻| 精品福利视频导航大全| 国产精品偷伦免费视频观看的| 日韩综合网站| 中文字幕色网站| 色综合久久久网| 成人不用播放器| 成人在线中文字幕| 一区二区亚洲精品| aa片在线观看视频在线播放| 91官网在线免费观看| 色网站免费在线观看| 亚洲一区二区在线播放| 欧美色图首页| 波多野结衣av在线免费观看| 欧美日韩一级二级三级| 污污视频在线看| 欧美日韩免费精品| 久久99国产精品成人| 国产在线免费视频| 国产亚洲精品91在线|