[手把手教學] 怎麼做上傳 pdf 的 preview功能 w/ Ant Design

丟丟 Diuer
6 min read1 day ago

--

近期在做專案的時候發現,Ant Design 提供的 Upload 元件對於非圖檔的支援度有限(也可能是我還沒正確使用到)

先說明一下這次的需求:
- 可以上傳 jpg、png 及 pdf 檔案
- 即便欄位的初始值為 url,也能夠預覽
- 在重新上傳檔案後,不管是圖檔或是 pdf 檔都要能預覽

那為什麼會說對於非圖檔的支援度有限呢?

就例如我今天重新上傳了一個 pdf 檔案上去,欄位上會顯示文件的符號、也有刪除的功能,但還缺了可以預覽檔案的功能。

先說,對於已先賦予初始值( props.fileList)的 Upload 元件來說,就算是 pdf 檔,在 preview 這功能也是正常的呦!

capture from Ant Design
Capture from Ant Design

如上圖的左下方,即便是我添加上 accept=”.jpg, .png, .pdf”(允許上傳pdf)、通過驗證、將該值寫回表單資料裡,最終依然無法讓這個檔案可以被預覽。

首先!

我這次的案例並不會在使用者上傳完檔案後就直接 call API 去實際儲存到 server,只是想要做個 local 端的簡易 preview、待送出表單時再一併 call API,所以對於 Upload 這個元件我傳入了 beforeUpload 這個 props,以阻擋該元件會預設尋找 props.action 裡所給的 url。

後來我查看了幾次 Ant Design 官網的文件,發現僅有設定「是否開啟 preview 的 boolean」及「可傳入 onPreview 的 function」,但就算我都帶入了還是被元件本身擋了下來⋯⋯

最終,在文件中看到了可以帶入 itemRender 這個 function,有提供了相當程度的客製彈性!

先來看看可取用的參數吧~

capture from Ant Design

originNode:為 Upload 元件本身預設對於上傳後該檔案的一切呈現與功能。
file:當前上傳的那個檔案。
fileList:當前已存在該欄位的所有檔案資料。
actions:提供幾個元件本身可以用的 method

但第 1 個及第 4 個參數,對上傳 pdf 來說依舊會沒有辦法 preview 的,因為在元件上傳後的預設反應就已經先阻擋了 pdf 可以使用 preview 這件事。

所以最後我做了個不專業的 itemRender 以滿足現階段的需求!

我做的事分成了幾個部分

第一,上傳完的元件顯示,還是使用了 Image 元件去表示使用者上傳的檔案類型;
因為需求上允許圖檔及 pdf 檔,所以在標示上我是直接將 Image.src 設定為上傳檔案的 thumbUrl,並在 fallback props 去給予該檔案類型的 icon url。

第二,不論是圖檔或是 pdf,都需要有 preview及 remove 的功能,所以我加了自己定義的 Button,也因 remove 功能沒有遇上問題,所以這部分的實作依舊使用元件提供的 function;
至於 preview 的部分,是透過點擊後開啟新分頁的方式,那 url 的來源就是利用上傳圖檔所產生的 File 再透過 URL.createObjectURL 來取得的。

第三,功能都齊了但就是客製的 itemRender 在樣式跟其他元件差異很大!所以我就找了原本 Upload 元件有在用的 className 並套用在對應的 DOM 上,以盡可能地讓樣式看起來是一致的。

最終的 code 如下:

const uploadItemRender = (
originNode: React.ReactElement,
file: UploadFile,
fileList: Object[],
actions: { download: Function; preview: Function; remove: Function },
) => (
<div className="ant-upload-list-item">
{file.name && (
<AntImage
src={file.thumbUrl}
fallback={
file.name.substring(file.name.length - 4) === ".pdf"
? "https://cdn-icons-png.flaticon.com/512/201/201153.png"
: "https://cdn-icons-png.flaticon.com/512/44/44289.png"
}
preview={false}
alt={file.name}
/>
)}

<div className="ant-upload-list-item-actions d-flex mt-1">
{!isEmpty(file.originFileObj) && (
<Button
shape="circle"
size="small"
icon={<EyeOutlined />}
type="link"
href={URL.createObjectURL(file.originFileObj)}
target="_blank"
/>
)}

<Button
className="ant-btn-variant-text ant-upload-list-item-action"
shape="circle"
size="small"
icon={<DeleteOutlined />}
onClick={() => actions.remove()}
/>
</div>
</div>
);

最後的成果如下圖們,
第 1、2 張是分別上傳圖檔及 pdf 檔、第 3 張是hover上去的樣子。

終於能夠 preview pdf 檔了!

以上就是 怎麼做上傳 pdf 的 preview功能 的筆記內容,有任何問題和建議都歡迎互相交流喔!

--

--

No responses yet