node實現rar格式壓縮


背景

由於公司的CMS系統里,只接受rar格式壓縮的文件,所以沒法直接使用nodejs里提供的zip壓縮組件。只能從winRar軟件入手了,但網上沒有多少這方面相關的東西,所以下面也是自己嘗試着在做。

github地址:https://github.com/cedrusweng/win-rar

主要解決的幾個問題

rar軟件的位置獲取問題

通過node的命令行組件child_process,運行注冊表查詢命令REG query ‘鍵值名’,可以查找出相關軟件的目錄,然后使用正則表達式對結果進行匹配,返回軟件目錄。命令如下:

var cp=require('child_process');

cp.exec("reg query HKEY_CLASSES_ROOT\\WinRAR\\shell\\open\\command /ve", function(e, stdout, stderr) {
                    if(!e){
                        var str = stdout.match(/\"([^\"]+)\"/)[0];
                        if(str){
                            console.log('已經找到winRar程序,詳細地址為:'+str);

                        }else{
                            console.log('沒有找到winRar程序,無法完成壓縮功能!');
                        }
                    }
});

通過上面的命令可以獲取到注冊表中winRar程序的絕對路徑,如果你安裝正確應該獲得下面這個結果

image

環境變量設置問題

通過上面一步可以解決winRar軟件的路徑問題,但怎么才能方便地調用rar命令呢?我的第一個想法就是設置環境變量。通過運行命令行命令set path=%path%;新目錄,node命令如下:

cp.exec("set path=%path%"+";c:\\", function(e, stdout, stderr) {
            if(!e){
                console.log("環境變量path添加;c:\\成功!")
            }
});

獲取結果如下

image

到這里好像沒有問題。其實這里存在一個問題,這個環境變量設置是臨時的,在命令行關閉時這個環境變量就消失了。

無法在下一次調用命令行時使用,所以到這里來說,無法再進行下去了。

在調用的過程中,設置環境變量和運行命令是兩個步驟:

cp.exec("set path=%path%"+";c:\\", function(e, stdout, stderr) {
            if(!e){
                console.log("環境變量path添加;c:\\成功!");
                cp.exec('rar a -r f:/build/1.rar f:/xc/gulpfile.js',{encoding:'binary'},function(e,stin,stout){
                    console.log(e,stin,stout);
                });
            }
});

下面的方法運行並不能得到正確的結果。

image

直接調用winRar程序

解決方法有兩種,一種是笨方法,讓每個使用者,手動去配置環境變量。第二種是直接在命令行使用完整的程序路徑調用。

第一種方法,是最后的一步,實在不行才用這個方法,手動畢竟不是程序員該干的事。

第二種方法,測試可以使用,運行以下代碼,

cp.exec('"C:\\Program Files\\WinRAR\\WinRAR.exe" a -r f:/build/1.rar f:/xc/gulpfile.js',{encoding:'binary'});

將得到以下結果

imageimage

這里需要注意的是當路徑中有空格的時候,可以把整個路徑用引號包起來,不然會導致命令行命令運行失敗。

但這里必須忍受,下面這個窗口。

image

一些擴展

1、在壓縮的過程中,會包含上級文件夾,如何去壓縮只包含文件不包含文件夾的,壓縮包形如下面的圖示

image

2、對文件目錄包含的內容進行過濾,並對需要的文件及子文件夾進行壓縮,如文件目錄如下,我只想壓縮里面的htm,txt文件。

image

可以通過node的fs組件,然后調用fs.readdirSync()方法,然后對得到的數組進行過濾。

需要注意的問題

1、程序運行路徑中有空格時,別忘記用引號把路徑包上,以及對符號進行轉義。

2、在調用rar壓縮文件時,當過濾掉的目錄中含有和當前目錄相同文件名的文件時,也會把子目錄對應的文件壓縮進來。(見補充代碼)

在文件結構如下

image

運行下面的命令

cp.exec('"C:\\Program Files\\WinRAR\\WinRAR.exe" a -r f:/build/1.rar f:/xc/gulp.js',{encoding:'binary'});

雖然在本目錄下沒有對應的文件,但rar程序會自動,遍歷子文件夾,最后生成如下的壓縮包

image

因為這個組件文件夾里包含gulp.js文件。這會使上面的過濾出現問題,我還沒解決,還沒想到辦法。

總結

基本上面的功能都完成了,只是構建工具里的一小部分,完成對源文件合並,壓縮,md5后,添加的一個小功能。后面還會找一資料看一下,怎么解決上面的問題。在這里哪位大俠有解決辦法,可以評論或私信,非常感謝。

 

附錄一:winRar命令

配置完,winRar的環境變量,直接運行 rar,可以得到下面這些個列表

使用示例:

rar a contact.rar contact.dat

如果contact.rar不存在將創建contact.rar文件;如果contact.rar壓縮包中已有contact.ext,將更新壓縮包中的contact.ext

rar a -r -v2000 -sfx vudroid2.rar vudroid2

遞歸壓縮vudroid2目錄下全部文件為 2M 大小分卷自解壓文件(自解壓文件就是壓縮文件中已經包含了解壓縮的工具,無需用戶自己安裝解壓縮工具) vudroid2.part1.sfx,vudroid2.part2.rar,vudroid2.part3.rar 等,將命令a換成命令m可將文件壓縮后刪除

rar x contact.rar

用絕對路徑來解壓,如果是rar x contact.rar ~/hehe/,前提是hehe文件夾要存在。就是解壓到當前路徑的hehe目錄下,還有一個是e參數,解釋是加壓到當前目錄下,在ubuntu 10.04我實驗過,rar e和rar x都可以用相對路徑和絕對路徑解壓,這一點我也不知道是為什么

rar a -pzaba contact1.rar contact.dat

使用密碼 zaba 壓縮contact1.rar文件

附錄二:node的child_process組件

child_process.exec(command, [options], callback)   來源:《Node.js v4.2.4 手冊 & 文檔-child_process

  • command {String} 將要執行的命令,用空格分隔參數
  • options {Object}
    • cwd {String} 子進程的當前工作目錄
    • env {Object} 環境變量鍵值對
    • encoding {String} 編碼(缺省為 'utf8')
    • shell {String} 運行命令的 shell(UNIX 上缺省為 '/bin/sh',Windows 上缺省為 'cmd.exe'。該 shell 在 UNIX 上應當接受 -c 開關,在 Windows 上應當接受 /s /c 開關。在 Windows 中,命令行解析應當兼容 cmd.exe。)
    • timeout {Number} 超時(缺省為 0)
    • maxBuffer {Number} 最大緩沖(缺省為 200*1024)
    • killSignal {String} 結束信號(缺省為 'SIGTERM')
  • callback {Function} 進程結束時回調並帶上輸出
    • error {Error}
    • stdout {Buffer}
    • stderr {Buffer}
  • 返回:ChildProcess 對象

在 shell 中執行一個命令並緩沖輸出。

child = exec('cat *.js bad_file | wc -l',
  function (error, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
    if (error !== null) {
      console.log('exec error: ' + error);
    }
});

回調參數為 (error, stdout, stderr)。當成功時,error 會是 null。當遇到錯誤時,error 會是一個Error 實例,並且 err.code 會是子進程的退出代碼,同時 err.signal 會被設置為結束進程的信號名。

第二個可選的參數用於指定一些選項,缺省選項為:

{ encoding: 'utf8',
  timeout: 0,
  maxBuffer: 200*1024,
  killSignal: 'SIGTERM',
  cwd: null,
  env: null }

如果 timeout 大於 0,則當進程運行超過 timeout 毫秒后會被終止。子進程使用 killSignal 信號結束(缺省為 'SIGTERM')。maxBuffer 指定了 stdout 或 stderr 所允許的最大數據量,如果超出這個值則子進程會被終止。

補充:

注意問題2的解決方法

對於同文件名,排除的文件夾包含,去除的方法,在命令 開關里。

經過實驗可以使用下面這個命名來處理

開關

r0 只遞歸通配符名稱的子目錄

rar a -r0 壓縮文件名.rar 文件列表


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM