node實現rar格式壓縮

背景

因爲公司的CMS系統裏,只接受rar格式壓縮的文件,因此無法直接使用nodejs裏提供的zip壓縮組件。只能從winRar軟件入手了,但網上沒有多少這方面相關的東西,因此下面也是本身嘗試着在作。javascript

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

主要解決的幾個問題java

rar軟件的位置獲取問題

經過node的命令行組件child_process,運行註冊表查詢命令REG query ‘鍵值名’,能夠查找出相關軟件的目錄,而後使用正則表達式對結果進行匹配,返回軟件目錄。命令以下:node

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程序的絕對路徑,若是你安裝正確應該得到下面這個結果git

image

環境變量設置問題

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

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

獲取結果以下github

image

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

沒法在下一次調用命令行時使用,因此到這裏來講,沒法再進行下去了。shell

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

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

一些擴展

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

image

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

image

能夠經過node的fs組件,而後調用fs.readdirSync()方法,而後對獲得的數組進行過濾。

須要注意的問題

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

二、在調用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 文件列表
相關文章
相關標籤/搜索