那為什麼會說對於非圖檔的支援度有限呢?
就例如我今天重新上傳了一個 pdf 檔案上去,欄位上會顯示文件的符號、也有刪除的功能,但還缺了可以預覽檔案的功能。
先說,對於已先賦予初始值( props.fileList)的 Upload 元件來說,就算是 pdf 檔,在 preview 這功能也是正常的呦!
如上圖的左下方,即便是我添加上 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,有提供了相當程度的客製彈性!
先來看看可取用的參數吧~
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功能 的筆記內容,有任何問題和建議都歡迎互相交流喔!