日期: 2021/08/18 天气:晴

    参考地址

    1. /*
    2. * @Description: 多张图片上传压缩
    3. * @Author: 惜神
    4. * @Date: 2021-08-17 16:45:27
    5. */
    6. const fs = require("fs");
    7. const JSZip = require("jszip");
    8. const image = require("imageinfo");
    9. const zip = new JSZip();
    10. const request = require('request');
    11. const path = require('path');
    12. const QRCode = require('qrcode');
    13. /**
    14. * 创建新的文件夹用于保存图片(如果有自己的文件夹,可以不使用)
    15. * @author: 惜神
    16. * @param {String} dirname 创建文件路径
    17. * @Date: 2021-08-17 17:36:07
    18. */
    19. const mkdirSync = (dirname) => {
    20. if (fs.existsSync(dirname)) {
    21. return true;
    22. } else {
    23. if (mkdirSync(path.dirname(dirname))) {
    24. fs.mkdirSync(dirname);
    25. return true;
    26. }
    27. }
    28. return false
    29. }
    30. /**
    31. * @author: 惜神
    32. * @param {String} folderPaths 压缩文件路径
    33. * @param {String} outPath 压缩文件输出路径
    34. * @Date: 2021-08-17 17:35:13
    35. */
    36. const packZipList = (folderPaths, outPath) => {
    37. const lists = getFiles.getFileList(folderPaths); //获取文件夹里的所有图片文件值
    38. for (let i = 0; i < lists.length; i++) {
    39. const data = fs.readFileSync(`${folderPaths}${lists[i].filename}`);
    40. const suffix = lists[i].filename.split('.')[1];
    41. zip.file(`photo_${i}.${suffix}`, data, { base64: true });
    42. delFile(`${folderPaths}${lists[i].filename}`, folderPaths) //调用删除方法
    43. }
    44. zip
    45. .generateNodeStream({ type: 'nodebuffer', streamFiles: true })
    46. .pipe(fs.createWriteStream(outPath)) //打包后的包名可以自己根据需求定义,路径可以根据需求更改
    47. .on('finish', () => {
    48. console.log(`${outPath} written.`); //管道写完数据后,打印出提示
    49. });
    50. }
    51. /**
    52. * 读取文件list
    53. * @author: 惜神
    54. * @param {String} path 文件夹路径
    55. * @Date: 2021-08-17 17:34:21
    56. */
    57. const readFileList = (path, filesList) => {
    58. const files = fs.readdirSync(path);
    59. files.forEach((item) => {
    60. const stat = fs.statSync(`${path}${item}`);
    61. if (stat.isDirectory()) {
    62. //递归读取文件
    63. readFileList(`${path}${item}/`, filesList)
    64. } else {
    65. let obj = {};//定义一个对象存放文件的路径和名字
    66. obj.path = path;//路径
    67. obj.filename = item//名字
    68. filesList.push(obj);
    69. }
    70. })
    71. }
    72. /**
    73. * 获取文件
    74. * @author: 惜神
    75. * @Date: 2021-08-17 17:33:58
    76. */
    77. const getFiles = {
    78. //获取文件夹下的所有文件
    79. getFileList: (path) => {
    80. const filesList = [];
    81. readFileList(path, filesList);
    82. return filesList;
    83. },
    84. //获取文件夹下的所有图片
    85. getImageFiles: (path) => {
    86. const imageList = [];
    87. this.getFileList(path).forEach((item) => {
    88. const ms = image(fs.readFileSync(`${item.path}${item.filename}`));
    89. ms.mimeType && (imageList.push(item.filename))
    90. });
    91. return imageList;
    92. }
    93. };
    94. /**
    95. * 检查是否是空文件夹
    96. * @author: 惜神
    97. * @param {String} file 文件路径
    98. * @Date: 2021-08-18 14:07:16
    99. */
    100. const fileExists = (file) => {
    101. fs.access(`${file}`, fs.constants.F_OK, (err) => {
    102. if(err) {
    103. return false
    104. }
    105. fs.readdir(`${file}/`,function(err,fileArr){
    106. if(err){
    107. return false
    108. }
    109. if(fileArr.length === 0) {
    110. return false
    111. }
    112. return true
    113. })
    114. });
    115. }
    116. /**
    117. * 移动文件夹
    118. * @author: 惜神
    119. * @param {String} dstpath 加载文件夹路径
    120. * @param {String} sourcePath 来源文件夹路径
    121. * @Date: 2021-08-18 12:16:53
    122. */
    123. const mvFiles = (dstpath, sourcePath) => {
    124. const status = fileExists(sourcePath);
    125. if(!status) return;
    126. fs.rename(sourcePath, dstpath, (err) => {
    127. if (err) {
    128. console.log('move file',err)
    129. }
    130. mkdirSync(sourcePath)
    131. })
    132. }
    133. /**
    134. * 删除文件下的文件
    135. * @author: 惜神
    136. * @param {String} path 文件夹下所有图片的路径
    137. * @param {String} reservePath 文件夹路径
    138. * @Date: 2021-08-17 17:26:25
    139. */
    140. const delFile = (path, reservePath) => {
    141. if (fs.existsSync(path)) {
    142. if (fs.statSync(path).isDirectory()) {
    143. let files = fs.readdirSync(path);
    144. files.forEach((file, index) => {
    145. let currentPath = `${path}/${file}`;
    146. if (fs.statSync(currentPath).isDirectory()) {
    147. delFile(currentPath, reservePath);
    148. } else {
    149. fs.unlinkSync(currentPath);
    150. }
    151. });
    152. if (path != reservePath) {
    153. fs.rmdirSync(path);
    154. }
    155. } else {
    156. fs.unlinkSync(path);
    157. }
    158. }
    159. }
    160. /**
    161. * 图片链接处理
    162. * @author: 惜神
    163. * @param {String} dstpath 打包图片路径
    164. * @param {String} imageList 图片数组
    165. * @Date: 2021-08-18 12:17:36
    166. */
    167. const linkTodo = async (dstpath, imageList) => {
    168. if(imageList && imageList.length === 0) return;
    169. mkdirSync(dstpath);
    170. for (const item of imageList) {
    171. const arg = new URL(item);
    172. const fileName = arg.pathname.split('/').slice(-1)[0];
    173. const downloadUrl = `${dstpath}/${fileName}`;
    174. request(item).pipe(fs.createWriteStream(downloadUrl))
    175. }
    176. }
    177. /**
    178. * code 处理
    179. * @author: 惜神
    180. * @param {String} dstpath 打包图片路径
    181. * @param {String} codeList code数组
    182. * @Date: 2021-08-18 12:18:17
    183. */
    184. const codeTodo = async (dstpath, codeList) => {
    185. if(codeList && codeList.length === 0) return;
    186. mkdirSync(dstpath);
    187. codeList.forEach(async (code, index) => {
    188. const fileName = `code_${code}_${index}`;
    189. const downloadUrl = `${dstpath}/${fileName}.png`;
    190. try {
    191. await QRCode.toFile(downloadUrl, code, {
    192. color: {
    193. dark: '#FFFF',
    194. light: '#0000'
    195. }
    196. })
    197. } catch (err) {
    198. console.error(err)
    199. }
    200. });
    201. }
    202. /**
    203. * 文件目录处理
    204. * @author: 惜神
    205. * @param {*} dstpath 打包图片路径
    206. * @param {*} sourcePath 来源图片路径
    207. * @Date: 2021-08-18 12:19:42
    208. */
    209. const folderTodo = async (dstpath, sourcePath) => {
    210. await mvFiles(dstpath, sourcePath);
    211. }
    212. /**
    213. * @author: 惜神
    214. * @param {String} dstpath 导出文件夹路径
    215. * @param {Array} imageList 图片链接
    216. * @param {Array} codeList code数组
    217. * @param {String} sourcePath 图片来源路径
    218. * @param {String} type 属输入类型
    219. * @param {String} outPath 压缩图片压缩包输出路径
    220. * @Date: 2021-08-17 16:58:47
    221. */
    222. (async ({ dstpath = "./img", imageList = [], outPath = "out.zip", type =
    223. "link", codeList = [], sourcePath = "./testImage" }) => {
    224. const map = {
    225. 'link': await linkTodo(dstpath, imageList),
    226. 'folder': await folderTodo(dstpath, sourcePath),
    227. 'code': await codeTodo(dstpath, codeList)
    228. }
    229. console.log(type)
    230. map[type];
    231. const folderPaths = `${dstpath}/`;
    232. setTimeout(() => { packZipList(folderPaths, outPath) }, 1000);
    233. })(
    234. /********* 图片链接参数 **********/
    235. {
    236. dstpath: "./img",
    237. imageList: [
    238. "https://cdn-scp.banu.cn/ideas/ideas/1617243660362-448561514.jpeg",
    239. "https://cdn-scp.banu.cn/ideas/ideas/1617243660548-7283341.jpeg"
    240. ],
    241. outPath: "out.zip",
    242. type: "link"
    243. }
    244. /********** 二维码字符串参数 **********/
    245. // {
    246. // dstpath: "./img",
    247. // codeList: ['1','2','桌位码:32'],
    248. // outPath: "out.zip",
    249. // type: "code"
    250. // }
    251. /********** 固定路径图片串参数 **********/
    252. // {
    253. // dstpath: "./img",
    254. // sourcePath: "./testImage",
    255. // outPath: "out.zip",
    256. // type: "folder"
    257. // }
    258. )