今天產品經理又提了一個需求.
在系統中上傳文件時,需要支持多文件和文件夾上傳,並且需要在文件上傳時需要將多文件壓縮成zip包,下載的時候,直接下載zip包
聽到這個需求,我的第一反應就是js應該沒有強大吧,因爲壓縮和訪問文件夾,涉及到了文件系統的讀取和修改,後來經過一番探索還真讓我給實現出來了.
主要用到的庫是 jszip
則 則這裏簡單對jszip做下簡單介紹,更詳細的功能和api請移步官網.
jszip是是一個創建,讀取和寫入.zip文件的js庫, api優化,簡單
瀏覽器支持
實現思路如下:
1:用戶選中文件或文件夾後,獲取文件對象,
2:遍歷獲取的文件對象 放入實例化的zip對象中
3:使用generateAsync()方法生成文件, 通過formdata提交到服務端
代碼如下:
此案例支持拖拽上傳多個文件, 支持選擇多個文件,選擇單個文件夾 此外可以使用 file-saver庫的saveAs對zip文件包保存到本地
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
文件壓縮上傳案例
<label name="myfile" for="myfile" style="display:block;width:200px;height:200px;border:1px solid #ddd"
:class="{'is-dragover': dragover}"
@drop.prevent="onDrop"
@dragover.prevent="onDragover"
@dragleave.prevent="dragover = false">
<input type="file" id="myfile" multiple webkitdirectory @change="selectFile" />
</label>
</div>
</template>
<script>
// @ is an alias to /src
import JSZip from 'jszip'
import axios from 'axios'
import { saveAs } from 'file-saver'
export default {
name: 'home',
components: {},
data () {
return {
dragover: false
}
},
mounted () {
},
methods: {
selectFile (even) {
var files = even.target.files
this.commmon(files)
},
onDrop (even) {
this.dragover = false
var files = even.dataTransfer.files
this.commmon(files)
},
commmon (files) {
var zip = new JSZip()
for (var i = 0; i < files.length; i++) {
var f = files[i]
zip.file(f.name, f)
}
zip.generateAsync({ type: 'blob' })
.then(function (content) {
saveAs(content, 'example.zip')
let formData = new FormData()
formData.append('file', content)
axios({
method: 'post',
url: '/framework/file/create',
data: formData,
withCredentials: true, // 默認的
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
})
},
onDragover () {
this.dragover = true
}
}
}
</script>
<style lang="scss">
.is-dragover{
border: 2px solid red !important
}
</style>
這裏說一下拖拽上傳文件, 主要是用到的原生事件是這三個
ondrop ondragover ondragleave
加上prevent 可以防止拖拽過程,瀏覽器 直接打開文件,阻止事件默認行爲.
在ondragover的事件上可以處理文件拖拽到了可放置的元素上,對用戶 進行友好提示.
ondrop 事件是文件拖拽到了元素上,鬆開鼠標時觸發, 這個時候可以通過事件拿到拖拽的文件列表 使用even.dataTransfer.files
jszip庫的常用api是這兩個
file(name, data [,options]) :創建zip文件,可以放入多個文件,支持多種文件格式String/ArrayBuffer/Uint8Array/Buffer/Blob/Promise/Nodejs stream,
name | type | description |
---|---|---|
name | string | the name of the file. You can specify folders in the name : the folder separator is a forward slash (“/”). |
data | String/ArrayBuffer/Uint8Array/Buffer/Blob/Promise/Nodejs stream | the content of the file. |
options | object | the options. |
Content of options
:
name | type | default | description |
---|---|---|---|
base64 | boolean | false |
set to true if the data is base64 encoded. For example image data from a <canvas> element. Plain text and HTML do not need this option. More. |
binary | boolean | false |
set to true if the data should be treated as raw content, false if this is a text. If base64 is used, this defaults to true , if the data is not a string, this will be set to true . More. |
date | date | the current date | the last modification date. More. |
compression | string | null | If set, specifies compression method to use for this specific file. If not, the default file compression will be used, see generateAsync(options). More. |
compressionOptions | object | null |
the options to use when compressing the file, see generateAsync(options). More. |
comment | string | null | The comment for this file. More. |
optimizedBinaryString | boolean | false |
Set to true if (and only if) the input is a “binary string” and has already been prepared with a 0xFF mask. |
createFolders | boolean | true |
Set to true if folders in the file path should be automatically created, otherwise there will only be virtual folders that represent the path to the file. More. |
unixPermissions | 16 bits number | null | The UNIX permissions of the file, if any. More. |
dosPermissions | 6 bits number | null | The DOS permissions of the file, if any. More. |
dir | boolean | false | Set to true if this is a directory and content should be ignored. More. |
generateAsync(options[, onUpdate]): 生成一個完整的zip的文件在當前文件目錄 返回一個promise
Arguments
name | type | default | description |
---|---|---|---|
options | object | the options to generate the zip file : | |
options.type | string | The type of zip to return, see below for the other types. Required. More. | |
options.compression | string | STORE (no compression) |
the default file compression method to use. More. |
options.compressionOptions | object | null |
the options to use when compressing the file. More. |
options.comment | string | The comment to use for the zip file. More. | |
options.mimeType | string | application/zip |
mime-type for the generated file. More. |
options.platform | string | DOS |
The platform to use when generating the zip file. More. |
options.encodeFileName | function | encode with UTF-8 | the function to encode the file name / comment. More. |
options.streamFiles | boolean | false | Stream the files and create file descriptors, see below. More. |
onUpdate | function | The optional function called on each internal update with the metadata. More. |
type
option
Possible values for type
:
base64
: the result will be a string, the binary in a base64 form.binarystring
(orstring
, deprecated): the result will be a string in “binary” form, using 1 byte per char (2 bytes).array
: the result will be an Array of bytes (numbers between 0 and 255) containing the zip.uint8array
: the result will be a Uint8Array containing the zip. This requires a compatible browser.arraybuffer
: the result will be a ArrayBuffer containing the zip. This requires a compatible browser.blob
: the result will be a Blob containing the zip. This requires a compatible browser.nodebuffer
: the result will be a nodejs Buffer containing the zip. This requires nodejs.
能不能做,要想看這個庫的api具不具備將文件轉化爲zip文件,通過以上兩個api,可以得知這個庫是支持的.
另外jszip庫也支持讀取本地和遠程的zip文件返回內部文件目錄,文件名.等信息,有興趣的朋友可以去嘗試一下