測試平台系列(91) 編寫oss管理頁面
大家好~我是
米洛
!我正在從0到1打造一個開源的介面測試平台, 也在編寫一套與之對應的
教程
,希望大家多多支援。歡迎關注我的公眾號
米洛的測開日記
,獲取最新文章教程!
回顧
上一節我們編寫好了oss
相關的crud介面,那這一節我們就得為oss數據的管理編寫一個新的頁面了。
即將做的是一個極度精簡的文件管理頁面
。
效果圖
因為我每次都是寫完一段程式碼,然後編寫對應教程,所以效果圖這種東西自然是不在話下:
圖片可以點擊下載,也可以刪除
。
編寫oss下載介面
在此之前還是先搞定下之前的作業
。
- 編寫隨機獲取文件名的方法
根據傳入的文件名,配合pity的打亂順序+當前時間戳,基本可以保證百分之90
的文件名衝突問題。
- 實現阿里雲的下載文件方法
調用get_object_to_file即可,並返回新的文件路徑。
- 封裝下載文件的方法
- 編寫下載文件介面
@router.get("/download")
async def download_oss_file(filepath: str):
"""
更新oss文件,路徑不能變化
:param filepath:
:return:
"""
try:
client = OssClient.get_oss_client()
# 切割獲取文件名
filename = filepath.split("/")[-1]
path = client.download_file(filepath, filename)
return PityResponse.file(path, filename)
except Exception as e:
return PityResponse.failed(f"下載失敗: {e}")
注意: 由於oss裡面的文件名
都是帶路徑的(目錄),所以我們split一下取出文件名
。
看看下載的效果
前端頁面部分
前端頁面表格那塊自然是傳統手藝
,不需要多說了。
值得注意的是下面這幾個地方:
-
上傳文件表單
上傳文件表單裡面有個Upload組件,這個比較特殊,我們需要手動上傳,我也踩了很久的坑。
這裡附上源碼:
這些幾乎都是根據antd官網的例子來的,其中Form.Item套了2層,demo就是這麼寫的,我試了下去掉一個還不行。
valuePropName固定要是fileList
。
-
上傳文件的http請求
由於前端未使用axios這樣的http請求庫,而是umi-request(自己封裝的)。
所以這邊還是說明一下怎麼使用:
這是文件上傳的方法,第一是要製造FormData
對象,並把文件數據append進去。
第二個關鍵就是requestType要指定為form
,這2點我摸索了挺久。
-
下載文件
用window.open或者a標籤鏈接到我們的download介面介面:
window.open(
${CONFIG.URL}/oss/download?filepath=${record.key})
-
全部程式碼
import {PageContainer} from "@ant-design/pro-layout";
import {Button, Card, Col, Divider, Form, Input, Modal, Row, Table, Upload} from "antd";
import {InboxOutlined, PlusOutlined} from "@ant-design/icons";
import {CONFIG} from "@/consts/config";
import {useEffect, useState} from "react";
import {connect} from 'umi';
import moment from "moment";
const Oss = ({loading, dispatch, gconfig}) => {
const [form] = Form.useForm();
const {ossFileList, searchOssFileList} = gconfig;
const [visible, setVisible] = useState(false);
const [value, setValue] = useState('');
const onDeleteFile = key => {
dispatch({
type: 'gconfig/removeOssFile',
payload: {
filepath: key
}
})
}
const listFile = () => {
dispatch({
type: 'gconfig/listOssFile',
})
}
const columns = [
{
title: '文件路徑',
key: 'key',
dataIndex: 'key',
render: key => <a href={`${CONFIG.URL}/oss/download?filepath=${key}`} target="_blank">{key}</a>
},
{
title: '大小',
key: 'size',
dataIndex: 'size',
render: size => `${Math.round(size / 1024)}kb`
},
{
title: '更新時間',
key: 'last_modified',
dataIndex: 'last_modified',
render: lastModified => moment(lastModified * 1000).subtract(moment().utcOffset() / 60 - 8, 'hours').format('YYYY-MM-DD HH:mm:ss')
},
{
title: '操作',
key: 'ops',
render: (record) => <>
<a onClick={() => {
window.open(`${CONFIG.URL}/oss/download?filepath=${record.key}`)
}}>下載</a>
<Divider type="vertical"/>
<a onClick={() => {
onDeleteFile(record.key);
}}>刪除</a>
</>
},
]
const normFile = (e) => {
if (Array.isArray(e)) {
return e;
}
return e && e.fileList;
};
const onUpload = async () => {
const values = await form.validateFields();
const res = dispatch({
type: 'gconfig/uploadFile',
payload: values,
})
if (res) {
setVisible(false)
setValue('')
listFile();
}
}
useEffect(() => {
if (value === '') {
dispatch({
type: 'gconfig/save',
payload: {searchOssFileList: ossFileList}
})
} else {
dispatch({
type: 'gconfig/save',
payload: {searchOssFileList: ossFileList.filter(v => v.key.toLowerCase().indexOf(value.toLowerCase()) > -1)}
})
}
}, [value])
useEffect(() => {
listFile();
}, [])
return (
<PageContainer title="OSS文件管理" breadcrumb={false}>
<Card>
<Modal width={600} title="上傳文件" visible={visible} onCancel={() => setVisible(false)} onOk={onUpload}>
<Form form={form} {...CONFIG.LAYOUT}>
<Form.Item label="文件路徑" name="filepath"
rules={[{required: true, message: '請輸入文件要存儲的路徑, 目錄用/隔開'}]}>
<Input placeholder="請輸入文件要存儲的路徑, 目錄用/隔開"/>
</Form.Item>
<Form.Item label="文件" required>
<Form.Item name="files" valuePropName="fileList" getValueFromEvent={normFile} noStyle
rules={[{required: true, message: '請至少上傳一個文件'}]}>
<Upload.Dragger name="files" maxCount={1}>
<p className="ant-upload-drag-icon">
<InboxOutlined/>
</p>
<p className="ant-upload-text">點擊或拖拽文件到此區域上傳
</p>
</Upload.Dragger>
</Form.Item>
</Form.Item>
</Form>
</Modal>
<Row gutter={[8, 8]} style={{marginBottom: 12}}>
<Col span={6}>
<Button type="primary" onClick={() => setVisible(true)}><PlusOutlined/>添加文件</Button>
</Col>
<Col span={12}/>
<Col span={6}>
<Input placeholder="輸入要查找的文件名" value={value} onChange={e => {
setValue(e.target.value);
}}/>
</Col>
</Row>
<Table rowKey={record => record.key} dataSource={searchOssFileList} columns={columns}
loading={loading.effects['gconfig/listOssFile']}/>
</Card>
</PageContainer>
)
}
export default connect(({loading, gconfig}) => ({loading, gconfig}))(Oss);
今天的內容就介紹到這裡,如今我們已經可以通過oss去管理我們的文件了,那我們要怎麼運用呢?
下一節給大家介紹,http請求支援文件上傳
功能。