js不借助後端,多文件拖拽壓縮上傳,支持選擇文件夾

今天產品經理又提了一個需求.

在系統中上傳文件時,需要支持多文件和文件夾上傳,並且需要在文件上傳時需要將多文件壓縮成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 trueMore.
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. RequiredMore.
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 (or string, 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庫api

 

另外jszip庫也支持讀取本地和遠程的zip文件返回內部文件目錄,文件名.等信息,有興趣的朋友可以去嘗試一下

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章