有个需求需要断网环境下上传文件,在有网环境下提交
附件需要提交到单独的文件服务器,返回文件服务器的id
框架是element-ui
设计思路
- 利用浏览器自带的indexDB,存储blob数据
- 利用localStorage缓存表单数据,indexDB的key
- 在有网的环境下,从indexDB获取数据,附件上传完成后,拿到id,拼接到表单的附件对象里面
封装indexDB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| if (!window.indexedDB) { window.alert('不支持indexDB数据库'); return false; } const debug = true; const log = debug ? window.console.log : () => { }
class HrIndexDB { db = null; dbName = null; storeName = null; constructor(storeName = 'storeName', dbName = "HR_INDEX_DB") { let request = window.indexedDB.open(dbName); this.storeName = storeName; this.dbName = dbName; request.onupgradeneeded = (event) => { this.db = event.target.result; if (!this.db.objectStoreNames.contains(storeName)) { const objectStore = this.db.createObjectStore(storeName, { keyPath: 'id' }); objectStore.createIndex('id', 'id', { unique: false }) } }
request.onerror = (event) => { }
request.onsuccess = (event) => { this.db = event.target.result; } } insert = (id, value) => { const transcation = this.db.transcation([this.storeName], 'readwrite'); transcation.objectStore(this.storeName).add({ id, value });
transcation.onerror = (event) => { log('insert error', event) } transcation.onsuccess = () => { log('insert success') } } select(id, cb) { const objectStore = this.db.transcation([this.storeName]).objectStore(this.storeName); const request = objectStore.get(id);
request.onsuccess = (event) => { cb(request.result, event) } } selectAsync(id) { return new Promise((resolve, reject) => { const objectStore = this.db.transcation([this.storeName]).objectStore(this.storeName); const request = objectStore.get(id);
request.onsuccess = event => { resolve(request.result, event) } request.onerror = (err) => { reject(err); console.log('indexDB selectError', err) } }) } del(id) { const objectStore = this.db.transcation([this.storeName], 'readwrite').objectStore(this.storeName, 'readwrite'); objectStore.delete(id); } listAll(cb) { const objectStore = this.db.transcation([this.storeName], 'readwrite').objectStore(this.storeName, 'readwrite'); objectStore.openCursor().onsuccess = event => { let cursor = event.target.result; if (cursor) { cb(cursor) cursor.continue() } else {
} } }
clearAll() { const objectStore = this.db.transcation([this.storeName], 'readwrite').objectStore(this.storeName, 'readwrite'); objectStore.openCursor().onsuccess = event => { let cursor = event.target.result; if (cursor) { cb(cursor) this.del(cursor.key) cursor.continue() } else { console.log('清空完成') } } } } export default HrIndexDB;
|
拦截element-ui上传
- 改写httpRequest方法
1 2 3 4 5
| <el-form> <el-form-item v-for="item in itemList" :key="item.key" :label="item.name" :prop="item.key"> <el-upload :httpRequest="customHttpRequest" :data="{item,standard}" /> </el-form-item> </el-form>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const hrIndexDB = new IndexDB() { data(){ return{ itemList:[ {name:"表单1",key:"formItem1",} ] } } methods:{ customHttpRequest(option){ const fileName = option.file.name; const {item,standard} = option.data.item; const count = item.attachmentList? item.attachmentList.length:0; const key = `attachment_${item.key}`; const blob = new Blob([option,file],{type:option.file.type}); const data = { key, blob, fileName, type:option.file.type, inputTime };
hrIndexDB.insert(key,data);
if(item.attachmentList){ item.attachmentList.push(data) }else{ item.attachmentList = [data]; }
} } }
|
存储到localStorage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| { data(){ return{ itemList:[ {name:"表单1",key:"formItem1"} ] } } methods:{ handleSave(){ this.itemList.forEach(item=>{ const key = `attachment_${item.key}`; localStorage.setItem(key,JSON.stringify(item)) }); } } }
|
提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| { methods:{ handleUpload(formData){ return new Promise((resolve,reject)=>{ axios({ url:'', method:'post' data:formData }) }) }, async submit(){ const taskList = []; const attachmentList = []; this.itemList.forEach(item=>{ const data = item; data.proofList = []; if(item.attachmentList){ item.attachmentList.forEach(attachment=>{ attachmentList.push({item,key:attachment.key}) }) } }) await this.handleUploadRemoteBatch(attachmentList); axios({ url:'', data:taskList, method:'post' })
} async handleUploadRemoteBatch(attachmentList){ const list = attachmentList; let index = 0; const Length = list.length;
while(index<Length){ const {key,item} = list[index]; const indexDBItem = await hrIndexDB.selectAsync(key); const {value} = indexDBItem; const {blob,fileName,type} = value; const file = new File([blob],fileName,{type}); const forData = new FormData(); formData.append('file',file); formData.append('fileName',fileName);
const {status,data} = await this.handleUpload(formData); const {id} = data; item.proofList.push({name:fileName,id}); index++ } } } }
|