javascript - 求解!小弟向使用过前端压缩工具JSZip!求助!

查看:150
本文介绍了javascript - 求解!小弟向使用过前端压缩工具JSZip!求助!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

  1. 1、事情是这样的:我们需要在客户端在上传他自己的文件的时候进行一下压缩,这个压缩工作是在客户端进行的,目的是节省服务端的计算资源和存储空间。

  2. 2、然后我们选择了github上的工具JSZip

  3. 3、在实际使用的过程中,我们遇到了这样的场景:用户需要同时上传多个文件,(文件类型不确定),当上传多个文件的时候会频繁出现这样的bug前端html上的input file 设置multiple,然后上传时选择多个文件,执行上传程序,并将文件压缩到zip包中时,会发现zip中少了一些文件(并不是总这样,跟文件大小和数量好像也没有直接关系,亲自测试过)另一个bug是:上传文件后,如果想再压缩另一个zip,必须刷新一下当前页面,否则,前一次选择的文件也会被压入到这次的zip当中。而且刷新页面后还是会出现压缩文件缺失的情况。
    具体代码和场景我下面尽量复原:

js代码:

require('cp');
require('./style.css');// 自定义样式
const JSZip = require('jszip');
const fileSaver = require('file-saver');
const zip = new JSZip();
$(() => {
// 写入自定义的js代码
  /* 客户端
   模型压缩开始 */
  $('#testJSZip').on('click', function() {
    var fileBox = $('#testFile');
    var fileList = fileBox[0].files;
    var flag = false;
    for (var i = 0; i < fileList.length; i++) {
      if (i === fileList.length - 1) {
        flag = true;
      }
      readFile(fileList[i], flag);
    }
  });
  function readFile(file, flag) {
    const reader = new FileReader();
    //  reader.readAsText(file);
    //  中文windows系统 txt 文本多数默认编码 gbk
    //  reader.readAsText(file, 'gbk');
    reader.readAsDataURL(file);
    reader.onloadend = function(e) {
      var result = reader.result;
      var objName = 'example';
      //  获取obj文件的文件名
      if (file.name.indexOf('.obj') !== -1) {
        var num = file.name.indexOf('.obj');
        objName = file.name.substring(0, num);
      }
      // 如果是图片文件,需要保存的时候把base64转为Blob二进制格式
      if (file.name.indexOf('.jpg' | '.png' | '.jpeg') !== -1) {
        result = convertBase64UrlToBlob(result);
      }
      zip.file(file.name, result, {type: 'blob'});
      console.log(zip);
      //  zip.folder().forEach();
      console.log(file.name);
      if (flag) {
        zip.generateAsync({
          type: 'blob',
          compression: 'DEFLATE', //  force a compression for this file
          compressionOptions: { //  使用压缩等级,1-9级,1级压缩比最低,9级压缩比最高
            level: 6,
          },
        }).then(function(content) {
          // see FileSaver.js
          console.log('content:' + content);
          Promise.resolve(true).then(function() {
            fileSaver.saveAs(content, objName + '.zip');
          });
        });
      }
    };
  }
  /* 客户端
   模型压缩结束 */
  /**
   * 将以base64的图片url数据转换为Blob
   * @param urlData
   * 用url方式表示的base64图片数据
   */
  function convertBase64UrlToBlob(urlData) {
    var bytes = window.atob(urlData.split(',')[1]);
    //  处理异常,将ascii码小于0的转换为大于0
    var ab = new ArrayBuffer(bytes.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < bytes.length; i++) {
      ia[i] = bytes.charCodeAt(i);
    }
    return new Blob([ab], {type: 'image/jpg'});
  }
});

ejs代码:

    <div class="col s12 m7">
        <div class="card horizontal">
            <div class="card-image">
            </div>
        </div>
        <input type="file" id="testFile" multiple>
    </div>

选择本地文件:


点击button开始压缩:

好了这是第一次压缩:可见文件是完整的,然后我们做下面的操作,不刷新页面的前提下,再选择两个文件,执行压缩:


结果前面的结果也被压缩到文件当中去了!!(缓存问题后面会提到)
接着,我们刷新页面重新上传:就会出现有时少个文件,有时多个文件的情况,当然多文件时也是上次选择过的文件


被这个东西搞得头疼了很久了,如果有用过的,求大神帮忙解答一下,不胜感激

解决方案

zip一直是引用同一个对象,自然会包含之前压缩进去的文件。

require('cp');
require('./style.css'); // 自定义样式
const JSZip = require('jszip');
const fileSaver = require('file-saver');
let zip;
$(() => {
  // 写入自定义的js代码
  /* 客户端
   模型压缩开始 */
  $('#testJSZip').on('click', function () {
    zip = new JSZip();  // 每次点击时,重新实例化JSZip对象
    // 以下不变

至于文件没压缩完整,是因为之前的文件没有压缩好,你就开始下载了。


大概是改成下面的感觉吧,不想写个页面出来测了。

require('cp');
require('./style.css'); // 自定义样式
const JSZip = require('jszip');
const fileSaver = require('file-saver');

$(() => {
  // 写入自定义的js代码
  /* 客户端
   模型压缩开始 */
  $('#testJSZip').on('click', async function () {
    var fileBox = $('#testFile');
    var fileList = Array.from(fileBox[0].files);
    let zip = new JSZip();
    let objName = 'example';
    for (const fileObject of fileList) {
      //  获取obj文件的文件名
      if (fileObject.name.indexOf('.obj') !== -1) {
        const num = file.name.indexOf('.obj');
        objName = file.name.substring(0, num);
      }
      zip = await zipFileAsync(zip, file);
    }
    saveFileAs(zip, objName);
  });

  function zipFileAsync(zip, file) {
    const promise = new Promise((resolve) => {
      const reader = new FileReader();
      //  reader.readAsText(file);
      //  中文windows系统 txt 文本多数默认编码 gbk
      //  reader.readAsText(file, 'gbk');
      reader.readAsDataURL(file);
      reader.onloadend = function (e) {
        var result = reader.result;

        // 如果是图片文件,需要保存的时候把base64转为Blob二进制格式
        if (file.name.indexOf('.jpg' | '.png' | '.jpeg') !== -1) {
          result = convertBase64UrlToBlob(result);
        }
        console.log(zip);
        //  zip.folder().forEach();
        console.log(file.name);        
        resolve(
          zip.file(file.name, result, {
            type: 'blob'
          }));
      };
    });
    return promise;
  }

  function saveFileAs(zip, objName) {
    zip.generateAsync({
      type: 'blob',
      compression: 'DEFLATE', //  force a compression for this file
      compressionOptions: { //  使用压缩等级,1-9级,1级压缩比最低,9级压缩比最高
        level: 6,
      },
    }).then(function (content) {
      // see FileSaver.js
      console.log('content:' + content);
      fileSaver.saveAs(content, objName + '.zip');
    });
  }

  /* 客户端
   模型压缩结束 */
  /**
   * 将以base64的图片url数据转换为Blob
   * @param urlData
   * 用url方式表示的base64图片数据
   */
  function convertBase64UrlToBlob(urlData) {
    var bytes = window.atob(urlData.split(',')[1]);
    //  处理异常,将ascii码小于0的转换为大于0
    var ab = new ArrayBuffer(bytes.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < bytes.length; i++) {
      ia[i] = bytes.charCodeAt(i);
    }
    return new Blob([ab], {
      type: 'image/jpg'
    });
  }
});

这篇关于javascript - 求解!小弟向使用过前端压缩工具JSZip!求助!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆