有个需求需要断网环境下上传文件,在有网环境下提交
附件需要提交到单独的文件服务器,返回文件服务器的id
框架是element-ui
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;
// 不存在objectStore实例,创建实例
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;
<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>
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}`;
//将上传的文件转换成blob
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];
}
}
}
}
{
data(){
return{
itemList:[
{name:"表单1",key:"formItem1"}
]
}
}
methods:{
handleSave(){
this.itemList.forEach(item=>{
const key = `attachment_${item.key}`;
localStorage.setItem(key,JSON.stringify(item))
});
}
}
}
{
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 = [];//上传完成后的
// 在拦截阶段,上传的存储到indexDB的数据
if(item.attachmentList){
item.attachmentList.forEach(attachment=>{
// 利用引用类型,把item传递过去,改变taskList里面 proofList字段
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++
}
}
}
}