需求描述
读取zip文件生成目录树,并提供zip的下载,解压之后的单个文件的下载,复制,以及展示。
引入相关依赖
// css
// element
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
// codemirror
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/codemirror.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/theme/idea.css">
// element
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
// codemirror
<script src="https://cdn.bootcdn.net/ajax/libs/codemirror/2.36.0/clike.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/codemirror.js"></script>
// jszip
<script src="https://cdn.bootcdn.net/ajax/libs/jszip/3.5.0/jszip.js"></script>
// FileSaver
<script src="https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2014-11-29/FileSaver.js"></script>
zip解压
// 创建目录树
async createTreeData() {
let newZip = new JSZip();
// this.zipData 为zip的blob文件流
const { files } = await newZip.loadAsync(this.zipData).catch(() => {
throw Error(`Could not load the ZIP project.`)
})
this.newZipFiles = files
this.findRoot({ files })
},
// 查找目录树 并生成目录树 目前是只生成二级目录 后面的目录都采用实时获取
findRoot(zip) {
let that = this
this.filesTree = []
const dirKeys = Object.keys(zip.files)
const root = Array.from(new Set(dirKeys.map(v => v.split('/')[0])))[0]
this.filesTree.push({
isFolder: true,
path: root,
label: root,
children: []
})
const zipFileKeys = dirKeys.sort((a, b) => a.split('/').length - b.split('/').length)
zipFileKeys.map((key, index) => {
const dirKeys = key.split('/')
let prevPath = dirKeys[0] + '/' + dirKeys[1]
const isExistDir = that.filesTree[0].children.filter(v => v.label === dirKeys[1])
const children = {
isFolder: dirKeys.length > 2,
path: prevPath,
label: dirKeys[1]
}
dirKeys.length > 2 && (children.children = [{label: null}])
if (isExistDir.length === 0) {
that.filesTree[0].children.push(children)
} else {
that.filesTree[0].children.concat(children)
}
})
// 过滤出二级目录中可以展示的文件
const defaultData = this.filesTree[0].children.filter(v => !v.isFolder)[0]
if (defaultData) {
this.currentFile = this.filesTree[0]
this.defaultExpandedKeys = [this.filesTree[0].label, defaultData.label]
// 获取默认展示的文件内容
this.getFilesDetails(defaultData)
}
}
获取zip压缩包解压之后的文件内容并交给codeMirror展示
// data为当前选中的目录树节点参数
getFilesDetails(data) {
this.currentFile = data
let that = this
if (!data.isFolder) {
// 这里的path是当前zip文件的绝对路径
this.newZipFiles[data.path].async('string').then(content => {
that.fileDetails = content
if (that.editor) {
that.editor.setValue(content)
} else {
// 声明codemirror实例 并将文件内容设置给codeMirror
that.editor = CodeMirror.fromTextArea(this.$refs.textarea, {
mode: 'text/x-java',
lineNumbers: true,
lint: true,
lineWrapping: true,
tabSize: 2,
cursorHeight: 0.9,
// 替换主题这里需修改名称
theme: 'idea',
readOnly: true
})
this.editor.setSize('auto', '650px')
that.editor.setValue(content)
}
})
}
},
下载单个文件
// newZipFiles 是zip文件解压之后得到的files;this.currentFile.path是当前选中的目录节点的文件绝对路径
this.newZipFiles[this.currentFile.path].async("blob").then(content => {
// content为文件blob文件流;this.currentFile.label为zip解压之后的文件名带格式后缀
saveAs(content, this.currentFile.label);
})
复制文件
// 复制文件
copyFileContent() {
if (this.currentFile.path) {
this.newZipFiles[this.currentFile.path].async('string').then(content => {
this.copy(content)
})
} else {
this.errorNotify('提示','请点击选中需要复制的文件')
}
},
copy (data) {
let str = ''
let save = function (e) {
e.clipboardData.setData('text/plain', data)
str = e.clipboardData.getData('Text')
e.preventDefault() // 阻止默认行为
}
document.addEventListener('copy', save)
document.execCommand('copy') // 使文档处于可编辑状态,否则无效
document.removeEventListener('copy', save) // 移除复制时间避免影响正常的复制
this.$message.success("复制成功")
return str
},