1.拖拽上传文件、文件夹,点击选择文件功能实现
直接上代码,
<template>
<div class="upload">
<div class="upload-content drop" v-show="list.length == 0" @dragover.prevent="ondragover" @drop="ondrop">
<img src="../img/import.svg" />
<div style="margin: 10px 0 12px 0">
<span class="drop-info">拖拽本地文件或文件夹至此,或</span>
<label for="customFileInput1" class="upload-drop-input" style="cursor: pointer">
<span style="color: #3674ef">添加文件</span>
<input type="file" id="customFileInput1" multiple class="fileInput1" @click="handleFileInputChange" />
</label>
</div>
<div class="upload-content-info aliInfo" v-if="infoType">
单次最多支持100个文件同时上传,总大小不超过5GB,请使用命令行工具ossutil、OSS SDK或OSS
API等方式,通过分片上传的方式进行上传文件操作。
</div>
<div class="upload-content-info" v-else>单次最多支持100个文件同时上传,总大小不超过5GB。</div>
</div>
<div class="upload-list" v-show="list.length != 0">
<div class="upload-list-header drop" @drop="ondrop" @dragover.prevent="ondragover">
拖拽本地文件或文件夹至此上传
</div>
<div style="display: flex; justify-content: space-between; margin-bottom: 18px">
<div class="upload-list-button">
<div @click="clear()" style="margin-right: 12px">清空列表</div>
<div>
<label for="customFileInput2" class="upload-drop-input" style="cursor: pointer">
<span>添加文件</span>
<input type="file" id="customFileInput2" multiple class="fileInput2" @click="handleFileInputChange" />
</label>
</div>
</div>
<div class="upload-list-info">
<div style="margin-right: 20px">
<span :class="{ warn: fileNum > 100 }" style="margin-right: 4px">{{ fileNum }}/100</span>
<span>文件</span>
</div>
<div>
<span>大小</span>
<span :class="{ warn: isLimit }" style="margin-left: 4px">{{ fileTotalSize }}</span>
</div>
</div>
</div>
<div class="listWarn" v-if="listWarn">
<div>
<img src="../img/warn.svg" />
<span style="margin-left: 8px" v-if="fileNum > 100 && !isLimit">
文件数量超过限制,单次上传文件的数量不能超过100,请先移除部分文件后再上传。</span
>
<span style="margin-left: 8px" v-if="isLimit && !(fileNum > 100)">
文件总大小超过限制,单次上传文件的总大小不能超过5GB,请先移除部分文件后再上传。</span
>
<span style="margin-left: 8px" v-if="isLimit && fileNum > 100">
文件总大小及数量超过限制,请先移除部分文件后再上传。</span
>
</div>
<img src="../img/cancel.svg" @click="cancelWarn" />
</div>
<uploadList :dataSource="list" @fileDelete="fileDelete" />
</div>
</div>
</template>
<script>
import uploadList from './uploadList.vue'
export default {
components: { uploadList },
props: {
version: {
default: false,
},
infoType: {
default: false,
},
},
data() {
return {
list: [], //包含文件夹,不展开全部
fileData: [], //全部已展开的文件
fileNum: 0,
fileTotalSize: 0,
totalSize: 0,
newArray: 0,
isLimit: false,
listWarn: false,
// infoType: false,
}
},
mounted() {
this.init()
},
methods: {
init() {
const div = document.querySelector('.drop')
div.ondragenter = e => {
e.preventDefault()
}
div.ondragover = e => {
e.preventDefault()
}
div.ondrop = e => {
e.preventDefault()
}
// document.getElementById('customFileInput1').addEventListener('change', this.handleFileInputChange.bind(this))
// document.getElementById('customFileInput2').addEventListener('change', this.handleFileInputChange.bind(this))
this.handleFileInputChange()
},
handleFileInputChange() {
console.log(1)
const fileInput1 = document.querySelector('.fileInput1')
const fileInput2 = document.querySelector('.fileInput2')
fileInput1.value = ''
fileInput2.value = ''
if (fileInput1) {
fileInput1.addEventListener('change', event => {
const selectedFiles = event.target.files
for (let i = 0; i < selectedFiles.length; i++) {
const file = selectedFiles[i]
console.log(i)
const existingIndex = this.list.findIndex(item => item.name === file.name)
if (existingIndex !== -1) {
// 如果存在相同名称的数据,用新数据替换旧数据
console.log('同名')
this.$set(this.list, existingIndex, { name: file.name, size: file.size, file })
this.$set(this.fileData, existingIndex, file)
this.list.forEach((item, index) => {
item.index = index
})
this.formatData()
} else {
// 如果不存在相同名称的数据,将新数据插入数组开头
this.list.unshift({ name: file.name, size: file.size, file })
this.fileData.unshift(file)
}
// }
this.formatData()
}
})
}
if (fileInput2) {
fileInput2.addEventListener('change', event => {
const selectedFiles = event.target.files
for (let i = 0; i < selectedFiles.length; i++) {
const file = selectedFiles[i]
const existingIndex = this.list.findIndex(item => item.name === file.name)
if (existingIndex !== -1) {
// 如果存在相同名称的数据,用新数据替换旧数据
console.log('同名')
this.$set(this.list, existingIndex, { name: file.name, size: file.size, file })
this.$set(this.fileData, existingIndex, file)
this.list.forEach((item, index) => {
item.index = index
})
this.formatData()
} else {
// 如果不存在相同名称的数据,将新数据插入数组开头
this.list.unshift({ name: file.name, size: file.size, file })
this.fileData.unshift(file)
}
}
this.formatData()
})
}
// fileInput1.removeEventListener()
// fileInput2.removeEventListener()
console.log(fileInput1)
},
ondragover(e) {
e.preventDefault()
},
async ondrop(e) {
//处理子文件夹逻辑
e.preventDefault()
const traverseEntries = (entries, directoryName) => {
for (const entry of entries) {
if (entry.isDirectory) {
// 处理目录
// console.log(entry.name, '我是文件夹中的文件夹')
const reader = entry.createReader()
reader.readEntries(subEntries => {
subEntries.forEach(subEntry => {
traverseEntries([subEntry]) // 递归处理子目录
})
})
} else {
// 处理文件
entry.file(file => {
// console.log(file.name, '我是文件夹中的子文件', file)
file.directoryName = directoryName
file.fullPath = entries[0].fullPath
this.fileData.unshift(file)
})
}
}
}
const array = Array.from(e.dataTransfer.items)
// console.log(e.dataTransfer.items.length, ' 上传文件总数', array[0].webkitGetAsEntry())
for (const index in array) {
const entry = array[index].webkitGetAsEntry()
// console.log(entry, 'entry')
if (entry) {
if (entry.isDirectory) {
// 处理根目录
// console.log(entry.name, '我是文件夹', entry)
const reader = entry.createReader()
reader.readEntries(subEntries => {
subEntries.forEach(subEntry => {
traverseEntries([subEntry], entry.name) // 开始递归处理目录
})
})
this.getSize([entry]).then(total => {
const reader = entry.createReader()
reader.readEntries(subEntries => {
// if (this.version) {
// this.list.unshift({
// name: entry.name,
// size: total,
// index: index,
// isDirectory: true,
// entry,
// subEntries: subEntries,
// })
// } else {
const existingIndex = this.list.findIndex(item => item.name === entry.name)
if (existingIndex !== -1) {
// 如果存在相同名称的数据,用新数据替换旧数据
console.log('同名')
this.$set(this.list, existingIndex, {
name: entry.name,
size: total,
index: index,
isDirectory: true,
entry,
subEntries: subEntries,
})
// this.$set(this.fileData, existingIndex, file)
this.list.forEach((item, index) => {
item.index = index
})
this.formatData()
// this.formatSize(
} else {
// 如果不存在相同名称的数据,将新数据插入数组开头
this.list.unshift({
name: entry.name,
size: total,
index: index,
isDirectory: true,
entry,
subEntries: subEntries,
})
// this.fileData.unshift(file)
}
// }
})
})
} else {
// 处理文件
entry.file(file => {
// if (this.version) {
// this.list.unshift({ name: file.name, size: file.size, file })
// this.fileData.unshift(file)
// } else {
console.log(file.name, '我是同名文件', file)
const existingIndex = this.list.findIndex(item => item.name === file.name)
if (existingIndex !== -1) {
// 如果存在相同名称的数据,用新数据替换旧数据
console.log('同名')
this.$set(this.list, existingIndex, { name: file.name, size: file.size, file })
this.$set(this.fileData, existingIndex, file)
this.list.forEach((item, index) => {
item.index = index
})
this.formatData()
} else {
// 如果不存在相同名称的数据,将新数据插入数组开头
this.list.unshift({ name: file.name, size: file.size, file })
this.fileData.unshift(file)
}
// }
})
}
}
}
// 等待list数组被填充
await new Promise(resolve => {
this.newArray += array.length
const checkList = () => {
if (this.list.length === this.newArray) {
resolve()
} else {
setTimeout(checkList, 0)
}
}
checkList()
})
// 为每个项添加索引
this.list.forEach((item, index) => {
item.index = index
})
this.formatData()
},
async getSize(entries) {
let total = 0
for (const entry of entries) {
if (entry.isFile) {
total += await this.getFileSize(entry)
} else if (entry.isDirectory) {
const reader = entry.createReader()
const subEntries = await this.readEntries(reader)
total += await this.getSize(subEntries) // 递归处理子目录
}
}
return total
},
async getFileSize(fileEntry) {
return new Promise(resolve => {
fileEntry.file(file => {
resolve(file.size)
})
})
},
async readEntries(reader) {
return new Promise(resolve => {
reader.readEntries(entries => {
resolve(entries)
})
})
},
formatData() {
let total = 0
this.list.forEach(item => {
total = total + item.size
})
// console.log(this.list)
this.totalSize = total
this.fileTotalSize = this.formatSize(total)
// console.log(this.fileTotalSize, this.list)
this.fileNum = this.list.length
this.listWarn = this.isLimit || this.fileNum > 100
const param = { fileList: this.list, fileData: this.fileData, limit: this.listWarn }
this.$emit('getData', param)
console.log(this.fileData, this.list, 6666666)
},
formatSize(sizeInBytes) {
if (sizeInBytes > 5 * 1024 * 1024 * 1024) {
// console.log(1, sizeInBytes)
this.isLimit = true
} else {
// console.log(2, sizeInBytes)
this.isLimit = false
}
// 定义换算单位
const units = ['Bytes', 'KB', 'MB', 'GB']
// 初始化大小和单位
let size = sizeInBytes
let unitIndex = 0
// 循环换算,直到大小小于1或者单位达到GB
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024
unitIndex++
}
size = Math.round(size * 100) / 100
return size.toFixed(2) + units[unitIndex]
},
fileDelete(record) {
if (record.index >= 0 && record.index < this.list.length) {
this.list.splice(record.index, 1)
}
if (record.isDirectory) {
// 删除匹配项
this.fileData = this.fileData.filter(item => item.directoryName !== record.name)
// console.log(this.fileData, record.name)
} else {
this.fileData = this.fileData.filter(item => {
if (item.directoryName) {
// 如果是文件夹,保留
return true
} else {
// 如果不是文件夹,删除同名文件
return item.name !== record.name
}
})
// this.fileData = this.fileData.filter(item => item.name != record.name)
}
if (this.list.length > 0) {
this.list.forEach((item, index) => {
item.index = index
})
}
console.log(this.list, this.fileData, 'del')
this.newArray = this.newArray - 1
this.formatData()
},
clear() {
this.newArray = 0
this.list = []
this.fileData = []
this.listWarn = false
this.isLimit = false
this.fileNum = 0
this.formatData()
},
cancelWarn() {
this.listWarn = false
},
},
}
</script>
以上是拖拽功能简单实现,下面放文件上传列表功能实现(包含进度条、文件状态)
<template>
<a-modal :visible="taskVisible" :footer="null" title="任务列表" :width="920" @cancel="cancelModal">
<div class="btn">
<a-button :disabled="canClear" @click="clearAll" class="cancelbtn">清除记录</a-button>
<a-button :disabled="canCancel" @click="cancelAll">全部取消</a-button>
<!-- <a-button v-else @click="startAll">全部开始</a-button> -->
</div>
<a-table :columns="type == 'ali' ? aliColumns : huaweiColumns" :data-source="formattedDataSource">
<template slot="name" slot-scope="item, record">
<overflow :text="record.name"></overflow>
</template>
<template slot="size" slot-scope="item, record">
<overflow :text="record.formattedSize"></overflow>
</template>
<template v-if="type == 'ali'" slot="uploadTo" slot-scope="item, record">
<overflow :text="uploadTo(record)"></overflow>
</template>
<template v-if="type == 'huawei'" slot="backet">
<overflow :text="bucketName"></overflow>
</template>
<template slot="status" slot-scope="item, record" class="status">
<a-progress
v-if="status[record.index] == '上传中'"
:percent="percent[record.index] || 0"
size="small"
:showInfo="false"
:strokeWidth="4"
:strokeColor="'#52C41A'"
/>
<img v-if="status[record.index] == '成功'" src="./compoment/img/success.svg" />
<img v-if="status[record.index] == '准备'" src="./compoment/img/ready.svg" />
<img v-if="status[record.index] == '失败'" src="./compoment/img/fail.svg" />
<span v-if="status[record.index] == '上传中'">{{
percent[record.index] != '' ? percent[record.index] + '%' : '0%'
}}</span>
<span v-if="status[record.index] != '上传中'">{{ status[record.index] }}</span>
</template>
<template slot="action" slot-scope="item, record">
<span class="action" v-if="status[record.index] == '上传中'" @click="cancelUpload(record.index)">取消</span>
<span
class="action"
v-if="status[record.index] == '失败'"
@click="retry(record.index)"
style="margin-right: 16px"
>重试</span
>
<span
class="action"
v-if="status[record.index] !== '准备' && status[record.index] !== '上传中'"
@click="clearFile(record.index)"
>清除记录</span
>
</template>
</a-table>
</a-modal>
</template>
<script>
import { aliyun, huawei, refreshBucketStat } from './api'
import overflow from '@/components/tableEllipsis/isOverflow.vue'
export default {
components: { overflow },
props: {
type: {
type: String,
default: 'ali',
},
},
data() {
return {
aliColumns: [
{
title: '文件名称',
width: '260px',
dataIndex: 'name',
scopedSlots: { customRender: 'name' },
},
{
title: '上传到',
width: '208px',
dataIndex: 'uploadTo',
scopedSlots: { customRender: 'uploadTo' },
},
{
title: '文件大小',
width: '124px',
dataIndex: 'size',
scopedSlots: { customRender: 'size' },
},
{
title: '状态',
width: '140px',
dataIndex: 'status',
scopedSlots: { customRender: 'status' },
},
{
title: '操作',
width: '128px',
dataIndex: 'action',
scopedSlots: { customRender: 'action' },
},
],
huaweiColumns: [
{
title: '文件名称',
width: '260px',
dataIndex: 'name',
scopedSlots: { customRender: 'name' },
},
{
title: '所属桶',
width: '208px',
dataIndex: 'backet',
scopedSlots: { customRender: 'backet' },
},
{
title: '文件大小',
width: '124px',
dataIndex: 'size',
scopedSlots: { customRender: 'size' },
},
{
title: '状态',
width: '140px',
dataIndex: 'status',
scopedSlots: { customRender: 'status' },
},
{
title: '操作',
width: '128px',
dataIndex: 'action',
scopedSlots: { customRender: 'action' },
},
],
taskVisible: false,
// fileList: [],
fileData: [],
aliUrl: '',
huaweiUrl: '',
aliHeaders: {},
huaweiHeaders: {},
huaweiSignature: '',
percent: [],
currentIndex: 0, // 当前上传的文件索引
status: [],
xhr: [],
indexs: [],
obsDate: '',
storageType: '',
docACL: 'default',
bucketName: '',
path: '',
}
},
computed: {
formattedDataSource() {
// dataSource格式化
return this.fileData.map((item, index) => ({
name: item.name,
index: index,
...item,
formattedSize: this.formatSize(item.size),
fullPath: this.path + (item.fullPath || '/' + item.name),
}))
},
canClear() {
return this.status.every(item => item === '上传中' || item === '准备')
},
canCancel() {
return this.status.every(item => item !== '上传中')
},
},
mounted() {},
methods: {
clearAll() {
this.fileData = []
},
cancelAll() {
for (const index in this.xhr) {
if (this.xhr[index] && this.xhr[index].readyState === 1) {
this.xhr[index].abort() // 中止请求
}
}
for (const i in this.status) {
if (this.status[i] != '成功') {
this.$set(this.status, i, '失败')
}
}
},
showTask() {
this.taskVisible = true
},
showModal(fileData, fileList, storageType, bucketName, path, version) {
this.path = path.slice(0, -1)
this.bucketName = bucketName
this.storageType = storageType
this.taskVisible = true
// debugger
if (this.fileData.length > 0) {
if (version) {
const initialStatus = Array(fileData.length).fill('准备')
const initialPercent = Array(fileData.length).fill('')
this.fileData = [...this.fileData, ...fileData]
this.status = [...this.status, ...initialStatus]
this.percent = [...this.percent, ...initialPercent]
const hasUploadingStatus = this.status.some(status => status === '上传中')
console.log(this.status, this.fileData)
// 如果没有上传中的状态,调用this.uploadNextFile()
if (!hasUploadingStatus) {
this.uploadNextFile()
}
//console.log('任务列表version', version)
} else {
//校验fileData是否和旧的this.fileData中有重名的file.name,去掉新的fileData中重名文件,将其他的拼接到this.fileData中
const uniqueFileData = fileData.filter(newFile => {
return !this.fileData.some(existingFile => existingFile.name === newFile.name)
})
const initialStatus = Array(uniqueFileData.length).fill('准备')
const initialPercent = Array(uniqueFileData.length).fill('')
this.fileData = [...this.fileData, ...uniqueFileData]
this.status = [...this.status, ...initialStatus]
this.percent = [...this.percent, ...initialPercent]
const hasUploadingStatus = this.status.some(status => status === '上传中')
// 如果没有上传中的状态,调用this.uploadNextFile()
if (!hasUploadingStatus) {
this.uploadNextFile()
}
}
} else {
this.status = Array(fileData.length).fill('准备')
this.percent = Array(fileData.length).fill('')
this.xhr = []
this.currentIndex = 0
this.fileData = fileData
// this.fileList = fileList
this.uploadNextFile()
}
},
alirefreshBucketStat() {
const param = {
accountId: this.$store.state.user.curAccount.id,
bucketId: this.$route.query.id,
}
refreshBucketStat(param).then(res => {
//console.log(res)
})
},
uploadNextFile() {
this.$parent.update()
// console.log(this.status, 'ssssssssssss', this.fileData)
const index = this.status.findIndex(status => status == '准备')
console.log(index, 'uploadNextFile indexindexindex')
if (index !== -1) {
const file = this.fileData[index]
this.status[index] = '上传中'
if (this.type == 'huawei') {
this.getHuawei(file, index)
}
if (this.type == 'ali') {
this.getAli(file, index)
}
this.alirefreshBucketStat()
// //console.log(index, '走到了下一个不是失败或者成功的文件', file)
}
},
getAli(file, index) {
const fileUrl = file.fullPath
const url = this.path ? this.path + '/' : this.path
const fileName = this.path ? this.path + '/' + file.name : file.name
const param = {
fileKey: fileUrl ? url + fileUrl.slice(1) : fileName,
bucketId: this.$route.query.id,
accountId: this.$store.state.user.curAccount.id,
fileAcl: this.docACL,
fileStorageClass: this.storageType,
contentType: file.type || 'application/octet-stream',
// contentType: 'application/x-png'',
}
aliyun(param).then(res => {
if (res.statusCode == 200) {
this.aliUrl = res.data.url
this.aliHeaders = res.data.headers
this.aliUpload(file, index)
} else {
for (const i in this.status) {
this.$set(this.status, i, '失败')
}
this.$message.error(res.message)
}
})
},
getHuawei(file, index) {
// //console.log(file, getContentType('png'), 123)
this.obsDate = this.getFormattedDate()
const fileUrl = file.fullPath ? file.fullPath.slice(1) : file.fullPath
const path = this.path ? this.path + '/' + fileUrl : fileUrl
const param2 = {
accountId: this.$store.state.user.curAccount.id,
bucketId: this.$route.query.id,
httpMethod: 'PUT',
objectKey: fileUrl ? path : (this.path ? this.path + '/' : '') + file.name,
// date: '',
contentType: file.type || 'application/octet-stream',
xObsHeaders: {
'x-obs-date': [this.obsDate],
'x-obs-storage-class': [this.storageType],
},
}
huawei(param2).then(res => {
this.huaweiUrl = res.data.domain
this.huaweiSignature = res.data.signature
this.huaweiUpload(file, index)
})
// huaweiBucket({ accountId: 1, limit: 10, page: 1 }).then(res => {
// //console.log(res)
// })
},
aliUpload(file, index) {
// //console.log(file, this.fileData, 6655, this.fileList)
const xhr = new XMLHttpRequest()
xhr.onerror = () => {
// 请求发生错误时,这里会执行
const index = this.fileData.findIndex(
item => item.name === file.name && item.directoryName === file.directoryName
)
this.$set(this.status, index, '失败')
console.error('请求发生错误', index)
this.uploadNextFile() // 上传下一个文件
}
xhr.onload = () => {
const index = this.fileData.findIndex(
item => item.name === file.name && item.directoryName === file.directoryName
)
if (xhr.status === 200) {
//console.log('文件上传成功!')
this.$set(this.status, index, '成功')
this.uploadNextFile() // 上传下一个文件
} else {
this.$set(this.status, index, '失败')
console.error('文件上传失败:', xhr.statusText)
this.uploadNextFile() // 上传下一个文件
}
}
xhr.upload.onprogress = e => {
const index = this.fileData.findIndex(
item => item.name === file.name && item.directoryName === file.directoryName
)
this.$set(this.percent, index, Math.floor((e.loaded / e.total) * 100))
}
const fullPath = file.fullPath
const fileNamePath = '/' + file.name
const url = fullPath ? '/' + this.path + fullPath : '/' + this.path + fileNamePath
xhr.open('PUT', this.aliUrl + url, true)
xhr.setRequestHeader('Authorization', this.aliHeaders.Authorization)
xhr.setRequestHeader('x-oss-date', this.aliHeaders['x-oss-date'])
xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream')
// xhr.setRequestHeader('x-oss-content-type', file.type || 'application/octet-stream')
// xhr.setRequestHeader('Content-Type', 'application/x-png')
xhr.setRequestHeader('x-oss-object-acl', this.aliHeaders['x-oss-object-acl'])
xhr.setRequestHeader('x-oss-storage-class', this.aliHeaders['x-oss-storage-class'])
this.xhr[index] = xhr
xhr.send(file)
},
huaweiUpload(file, index) {
const xhr = new XMLHttpRequest()
xhr.onerror = () => {
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
this.$set(this.status, index, '失败')
console.error('请求发生错误', index)
this.uploadNextFile() // 上传下一个文件
}
xhr.onload = () => {
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
if (xhr.status === 200) {
this.$set(this.status, index, '成功')
this.uploadNextFile() // 上传下一个文件
} else {
this.$set(this.status, index, '失败')
console.error('文件上传失败:', xhr.statusText)
this.uploadNextFile() // 上传下一个文件
}
}
xhr.upload.onprogress = e => {
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
this.$set(this.percent, index, Math.floor((e.loaded / e.total) * 100))
}
const fullPath = file.fullPath
const fileNamePath = '/' + file.name
const path = this.path ? '/' + this.path : this.path
const url = fullPath ? path + fullPath : path + fileNamePath
const encodedString = url.replace(/%/g, '%25').replace(/#/g, '%23')
xhr.open('PUT', this.huaweiUrl + encodedString, true)
xhr.setRequestHeader('Authorization', this.huaweiSignature)
xhr.setRequestHeader('x-obs-date', this.obsDate)
xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream')
xhr.setRequestHeader('x-obs-storage-class', this.storageType)
this.xhr[index] = xhr
xhr.send(file)
},
cancelUpload(index) {
this.$set(this.status, index, '失败')
this.$set(this.percent, index, 0)
const xhr = this.xhr[index]
if (xhr && xhr.readyState === 1) {
this.xhr[index].abort() // 中止请求
this.uploadNextFile()
}
//console.log(this.xhr, this.status, index, '取消上传')
},
clearFile(index1) {
this.fileData = this.fileData.filter((item, index) => index != index1)
this.status = this.status.filter((item, index) => index != index1)
this.percent = this.percent.filter((item, index) => index != index1)
this.xhr = this.xhr.filter((item, index) => index != index1)
//console.log(this.fileData)
},
retry(index) {
if (this.xhr.some(xhr => xhr && xhr.readyState === 1)) {
this.$set(this.status, index, '准备')
//console.log('retry', index, this.status, this.xhr, '准备重新上传')
this.$set(this.percent, index, 0)
} else {
this.$set(this.status, index, '上传中')
console.log('retry', index, this.status, this.xhr, '重新上传')
const file = this.fileData[index]
this.$set(this.percent, index, 0)
if (this.type == 'ali') {
const param = {
fileKey: file.directoryName ? file.directoryName + '/' + file.name : file.name,
accountId: this.$store.state.user.curAccount.id,
bucketId: this.$route.query.id,
fileAcl: this.docACL,
fileStorageClass: this.storageType,
contentType: file.type || 'application/octet-stream',
}
aliyun(param).then(res => {
if (res.statusCode == 200) {
this.aliUrl = res.data.url
this.aliHeaders = res.data.headers
this.xhr[index] = new XMLHttpRequest()
const xhr = this.xhr[index]
const fullPath = file.fullPath
const fileNamePath = '/' + file.name
const url = fullPath ? fullPath : fileNamePath
xhr.open('PUT', this.aliUrl + url, true)
xhr.setRequestHeader('Authorization', this.aliHeaders.Authorization)
xhr.setRequestHeader('x-oss-date', this.aliHeaders['x-oss-date'])
xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream')
xhr.setRequestHeader('x-oss-object-acl', this.aliHeaders['x-oss-object-acl'])
xhr.setRequestHeader('x-oss-storage-class', this.aliHeaders['x-oss-storage-class'])
xhr.onload = () => {
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
if (xhr.status === 200) {
this.$set(this.status, index, '成功')
this.$parent.update()
} else {
this.$set(this.status, index, '失败')
}
}
xhr.upload.onprogress = e => {
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
this.$set(this.percent, index, Math.floor((e.loaded / e.total) * 100))
//console.log(this.percent, '重新上传')
}
const form = new FormData()
form.append(file.name, file)
xhr.send(form)
} else {
this.$set(this.status, index, '失败')
this.$message.error(res.message)
}
})
}
if (this.type == 'huawei') {
this.obsDate = this.getFormattedDate()
const fileUrl = file.fullPath
const param2 = {
accountId: this.$store.state.user.curAccount.id,
bucketId: this.$route.query.id,
httpMethod: 'PUT',
objectKey: fileUrl ? fileUrl.slice(1) : file.name,
contentType: 'application/octet-stream',
xObsHeaders: {
'x-obs-date': [this.obsDate],
'x-obs-storage-class': [this.storageType],
},
}
huawei(param2).then(res => {
this.huaweiUrl = res.data.domain
this.huaweiSignature = res.data.signature
this.xhr[index] = new XMLHttpRequest()
const xhr = this.xhr[index]
xhr.onerror = () => {
// 请求发生错误时,这里会执行
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
this.$set(this.status, index, '失败')
console.error('请求发生错误', index)
// this.uploadNextFile() // 上传下一个文件
}
xhr.onload = () => {
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
if (xhr.status === 200) {
this.$set(this.status, index, '成功')
this.$parent.update()
// this.uploadNextFile() // 上传下一个文件
} else {
this.$set(this.status, index, '失败')
console.error('文件上传失败:', xhr.statusText)
// this.uploadNextFile() // 上传下一个文件
}
}
xhr.upload.onprogress = e => {
// const index = this.fileData.findIndex(
// item => item.name === file.name && item.directoryName === file.directoryName
// )
this.$set(this.percent, index, Math.floor((e.loaded / e.total) * 100))
//console.log(this.percent, '正常上传')
}
const form = new FormData()
form.append(file.name, file)
const fullPath = file.fullPath
const fileNamePath = '/' + file.name
const url = fullPath ? fullPath : fileNamePath
const encodedString = url.replace(/%/g, '%25').replace(/#/g, '%23')
xhr.open('PUT', this.huaweiUrl + encodedString, true)
xhr.open('PUT', this.huaweiUrl + encodedString, true)
xhr.setRequestHeader('Authorization', this.huaweiSignature)
xhr.setRequestHeader('x-obs-date', this.obsDate)
xhr.setRequestHeader('Content-Type', 'application/octet-stream')
xhr.setRequestHeader('x-obs-storage-class', this.storageType)
this.xhr[index] = xhr
xhr.send(form)
})
}
}
},
cancelModal() {
this.taskVisible = false
},
formatSize(sizeInBytes) {
const units = ['Bytes', 'KB', 'MB', 'GB']
let size = sizeInBytes
let unitIndex = 0
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024
unitIndex++
}
size = Math.round(size * 100) / 100
return size.toFixed(2) + ' ' + units[unitIndex]
},
getFormattedDate() {
const now = new Date()
const daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
const dayOfWeek = daysOfWeek[now.getUTCDay()]
const day = now.getUTCDate().toString().padStart(2, '0')
const month = months[now.getUTCMonth()]
const year = now.getUTCFullYear()
const time =
now.getUTCHours().toString().padStart(2, '0') +
':' +
now.getUTCMinutes().toString().padStart(2, '0') +
':' +
now.getUTCSeconds().toString().padStart(2, '0')
return `${dayOfWeek}, ${day} ${month} ${year} ${time} GMT`
},
uploadTo(record) {
const path = this.path ? record.fullPath : '/' + record.fullPath
return 'oss://' + this.bucketName + path
},
// containsChineseCharacters(str) {
// const chineseRegex = /[\u4e00-\u9fa5]/
// return chineseRegex.test(str)
// },
},
}
</script>