您好,登錄后才能下訂單哦!
在Nodejs中使用archiver-zip-encrypted庫加密壓縮文件出現(xiàn)報錯如何解決?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
在windows系統(tǒng)上測試時,發(fā)現(xiàn)會概率的出現(xiàn)以下異常:
events.js:174 throw er; // Unhandled 'error' event ^ Error: file data stream has unexpected number of bytes at ByteCounter. ( xxx\node_modules\yazl\index.js:162:99) at ByteCounter.emit (events.js:194:15) at endReadableNT (_stream_readable.js:1103:12) at process._tickCallback (internal/process/next_tick.js:63:19) Emitted 'error' event at: at ByteCounter. (xxx\node_modules\yazl\index.js:162:85) at ByteCounter.emit (events.js:194:15) at endReadableNT (_stream_readable.js:1103:12) at process._tickCallback (internal/process/next_t
我的本機環(huán)境是:
npm:6.9.0
node: v10.16.3
在另外一個同事的windows系統(tǒng)上測試,他那邊是上面異常必現(xiàn),對應的node版本是v10.15。
具體使用的代碼不貼了,基本上是參照官方 demo 來寫的,壓縮完成最后調(diào)用代碼如下所示:
archive.finalize().then(() => { // 到這里認為是壓縮完成,進行后續(xù)處理,實際并沒有,參照后面分析 anotherProcess(); }).catch(err => { // 壓縮出現(xiàn)異常處理... });
出現(xiàn)異常后一一檢查代碼和官方demo不一樣的地方,并沒有發(fā)現(xiàn)什么異常之處,網(wǎng)上搜索也沒有發(fā)現(xiàn)這種異常記錄。由于剛接觸JS,不是很熟,就從問題開始下手,找到出現(xiàn)問題的代碼,開始調(diào)試。
錯誤日志中提示是在 yzal/index.js 文件中發(fā)生異常,找到出現(xiàn)異常的代碼如下所示:
function pumpFileDataReadStream(self, entry, readStream) { var crc32Watcher = new Crc32Watcher(); var uncompressedSizeCounter = new ByteCounter(); var compressor = entry.compress ? new zlib.DeflateRaw() : new PassThrough(); var compressedSizeCounter = new ByteCounter(); readStream.pipe(crc32Watcher) .pipe(uncompressedSizeCounter) .pipe(compressor) .pipe(compressedSizeCounter) .pipe(self.outputStream, {end: false}); compressedSizeCounter.on("end", function() { entry.crc32 = crc32Watcher.crc32; if (entry.uncompressedSize == null) { entry.uncompressedSize = uncompressedSizeCounter.byteCount; } else { // 異常從這里拋出來的 if (entry.uncompressedSize !== uncompressedSizeCounter.byteCount) return self.emit("error", new Error("file data stream has unexpected number of bytes")); } entry.compressedSize = compressedSizeCounter.byteCount; self.outputStreamCursor += entry.compressedSize; writeToOutputStream(self, entry.getDataDescriptor()); entry.state = Entry.FILE_DATA_DONE; pumpEntries(self); }); }
從上面代碼可以看出來: uncompressedSizeCounter.byteCount
是從 pumpFileDataReadStream()
函數(shù) readStream 參數(shù)中獲取的屬性值,而 entry.uncompressedSize
也是函數(shù)的 entry 參數(shù)中獲取的屬性。接著找 pumpFileDataReadStream()
函數(shù)是從哪里調(diào)用的。
通過輸出日志得出 pumpFileDataReadStream()
函數(shù)是在以下面的代碼中被調(diào)用的:
ZipFile.prototype.addFile = function(realPath, metadataPath, options) { var self = this; metadataPath = validateMetadataPath(metadataPath, false); if (options == null) options = {}; var entry = new Entry(metadataPath, false, options); self.entries.push(entry); fs.stat(realPath, function(err, stats) { if (err) return self.emit("error", err); if (!stats.isFile()) return self.emit("error", new Error("not a file: " + realPath)); // 這里是文件的大小 entry.uncompressedSize = stats.size; if (options.mtime == null) entry.setLastModDate(stats.mtime); if (options.mode == null) entry.setFileAttributesMode(stats.mode); entry.setFileDataPumpFunction(function() { // readStream在這里創(chuàng)建的 var readStream = fs.createReadStream(realPath); entry.state = Entry.FILE_DATA_IN_PROGRESS; readStream.on("error", function(err) { self.emit("error", err); }); // 在這里被調(diào)用 pumpFileDataReadStream(self, entry, readStream); }); pumpEntries(self); }); };
從上面代碼可以看出來 entry.uncompressedSize
是stats.size,即文件的大小, readStream 是創(chuàng)建的文件流。但是在什么情況下兩者會不一樣呢?感覺只可能在文件還沒有讀取完,但是是什么原因?qū)е逻@種情況發(fā)生?由于對JS接觸的時間不長,沒有進行深入分析。最后在拋出異常的上面一行用 console.log 將兩個屬性的大小值都輸出,代碼如下所示:
if (entry.uncompressedSize == null) { entry.uncompressedSize = uncompressedSizeCounter.byteCount; } else { // 增加日志輸出 console.log("entry size: " + entry.uncompressedSize + ", uncompressedSize: " + uncompressedSizeCounter.byteCount); if (entry.uncompressedSize !== uncompressedSizeCounter.byteCount) return self.emit("error", new Error("file data stream has unexpected number of bytes")); }
在 archive.finalize()
時和 output 寫入流的 close 事件時(詳細參照官方的示例代碼),分別加上日志輸出,代碼如下所示:
archive.finalize().then(() => { // 到這里認為是壓縮完成,進行后續(xù)處理,實際并沒有,參照后面分析 console.log("finalize"); // anotherProcess(); }).catch(err => { // 壓縮出現(xiàn)異常 }); output.on('close', function() { console.log('close'); // 這個業(yè)務函數(shù)與上面finalize函數(shù)中的是互斥,不會同時存在 anotherProcess(); });
最后分別將 anotherProcess()
函數(shù)加到兩個異步回調(diào)中執(zhí)行,發(fā)現(xiàn)在 close 事件執(zhí)行時,兩個size輸出的大小一致,都是文件的大小。而在 finalize 場景測試發(fā)現(xiàn) uncompressedSize
要小于文件的大小。最后將 anotherProcess()
函數(shù)放在 close 事件回調(diào)函數(shù)中執(zhí)行,問題解決。
關(guān)于在Nodejs中使用archiver-zip-encrypted庫加密壓縮文件出現(xiàn)報錯如何解決問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。