iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 13
2
自我挑戰組

中年失業大叔的耍廢日記系列 第 13

第十三天:潮濕的雨天也要開始工作的週一

  • 分享至 

  • xImage
  •  

雨下個不停阿,但是待在家裡感覺會廢掉,還是出門尋找咖啡廳...

早上還是要寫作業,先整理一下dependency,把xmlrun發佈到npm,不然node/npm降版會有問題...

接下來開始繼續寫單元測試~~只寫了一半,就要吃午飯了...OK,下午繼續

下午看了一下文件,確認從OPCUA Server讀取資料節點的方式,看到不少東西...node-opcua官方文件很缺乏說明文字,反而在github上的issue track裡面有不少人貢獻code snippet XD,沒有仔細google還不會找到。知道找東西的方向,以後就方便了(可以寫整合測試?)

晚上回頭比較一下pptx viewer的資料,看起來前幾天調整過的xml to json的剖析器產出的格式大致上沒錯,現在需要的是把東西匯總起來成為單一的json。另外,我發現以前手賤,改了轉換後的名稱...tag名稱有sld的會改成slide,r:id的會改成rid之類,這個可能直接去調整viewer比較好。

彙整要怎麼做呢?處理的大致上都是ppt/底下的檔案...副檔名是.rels的把他的副檔名去掉當作key,內容則是從xml轉出的東西。副檔名是.xml的,則把presentation.xml的內容匯總到presentation這個key下面,其他的則依照ppt之下的目錄名來當作key,xml檔名當作下一層的key,然後把轉換後的json物件指派給這個key就可以。

媒體的部分會需要另外處理,今天先不管他。首先加一行:

let data = {relations:{},presentation:{},themes:{},slideMasters:{},slideLayouts:{},slides:{}};

.rels的資訊彙整到relations裡面,ppt/presentation.xml的資訊彙整到presentation,其他則根據目錄及xml檔名各自處理。程式改成:

<!DOCTYPE html>
<html>

<head>
    <title>file reader</title>
    <style>
        .dropable {
            width: 99%;
            height: 100px;
            background-color: #369;
            color: white;
            border: solid 3px gray;
            border-radius: 5px;
            padding: 5px 5px 5px 5px;
        }

        .message {
            width: 99%;
            background-color: #ddd;
            border: solid 1px gray;
            border-radius: 5px;
            overflow: auto;
        }

        .preview {
            font-size: 10px;
        }
    </style>
</head>

<body>
    <div id="target" class="dropable">
        <select id="encoding">
            <option value="utf-8">utf-8</option>
            <option value="big5">big5</option>
            <option value="gb2312">gb2312</option>
            <option value="shift-jis">shift-jis</option>
        </select>
        <input type="file" id="file" />
        <div id="console"></div>
    </div>
    <div id="panel" class="message"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako_inflate.min.js"></script>
    <script src="lib/zipfs.js"></script>
    <script src="node_modules/xmlrun/index.js"></script>
    <script>
        var _target = document.getElementById('target');
        var _message = document.getElementById('panel');
        var _file = document.getElementById('file');
        _file.onchange = function(e) {
            clearlog();
            if (this.files.length > 0) {
                var reader = new FileReader();
                reader.onload = (e) => {
                    var buffer = e.target.result;
                    log('file size: ' + buffer.byteLength);
                    let encoding = document.getElementById('encoding').value;
                    let start = new Date().getTime();
                    zipfs(buffer, pako.inflateRaw, encoding, (err, files) => {
                        let data = {relations:{},presentation:{},themes:{},slideMasters:{},slideLayouts:{},slides:{}};
                        if (!!err) return console.log(err);
                        log(`in callback: ${files.length} files extracted.`);
                        log(`${(new Date().getTime()-start)} ms`);
                        let str = '<table border="1" cellspacing="0" cellpadding="5" width="99%"><tr><th>file name</th><th>buffer length</th><th>last modified date</th><th>last modified time</th><th>compressed size</th><th>uncompressed size</th></tr>';
                        files.forEach(file => {
                            str += `<tr><td>${file.file_name}</td><td>${file.content.length}</td><td>${zipfs.formatMSDOSDate(file.last_modified_date)}</td><td>${zipfs.formatMSDOSTime(file.last_modified_time)}</td><td>${file.compressed_size}</td><td>${file.uncompressed_size}</td></tr>`;
                            str += `<tr><td colspan="6" class="preview" style="overflow-x:hidden">`;
                            if (checkExt(file.file_name, '.rels') && file.file_name.length > 5) {
                                let runner = xmlnode(zipfs.uintToString(file.content));
                                runner.setRunner('default', function(target) {
                                    if(!!target.child) {
                                        return target.child.reduce((acc, cur) => {
                                            Object.assign(acc, cur.run());
                                            return acc;
                                        }, {})
                                    }
                                    else return {};
                                });
                                runner.setRunner('Relationship', target => {
                                    let result = {};
                                    result[target.attr['Id']] = target.attr['Target'];
                                    result[target.attr['Target']] = target.attr['Id'];
                                    return result;
                                });
                                data.relations[file.file_name.substr(0, file.file_name.length-5)] = runner.run();
                            }

                            if (checkExt(file.file_name, '.xml')) {
                                let runner = xmlnode(zipfs.uintToString(file.content));
                                runner.setRunner('default', function(target) {
                                    let result = {};
                                    if(!!target.attr) {
                                        result = Object.keys(target.attr).reduce((pre, cur) => {
                                            pre[cur] = target.attr[cur];
                                            return pre;
                                        }, {});
                                    }
                                    if(!!target.val) result._value = target.val;
                                    if(!!target.child && Array.isArray(target.child) && target.child.length > 0) {
                                        target.child.forEach(c => {
                                            if(!result[c.tag]) {
                                                result[c.tag] = c.run();
                                            } else {
                                                if(Array.isArray(result[c.tag])) {
                                                    result[c.tag].push(c.run());
                                                } else {
                                                    let _t = result[c.tag];
                                                    result[c.tag] = [];
                                                    result[c.tag].push(_t);
                                                    result[c.tag].push(c.run());
                                                }
                                            }
                                        });
                                    }
                                    return result;
                                });
                                if(file.file_name === 'ppt/presentation.xml') {
                                    data.presentation = runner.run();
                                } else {
                                    let paths = file.file_name.split('/');
                                    if(Object.keys(data).indexOf(paths[1]) > -1) {
                                        data[paths[1]][file.file_name] = runner.run();
                                    }
                                }
                            }
                            if (checkExt(file.file_name, '.jpeg') || checkExt(file.file_name, '.jpg')) {
                                let im = new Image();
                                im.src = `data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}`;
                                if(im.width > 1024) {
                                    str += `<img width="1024px" src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                } else {
                                    str += `<img src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                }
                            }
                            if (checkExt(file.file_name, '.png')) {
                                let im = new Image();
                                im.src = `data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}`;
                                if(im.width > 1024) {
                                    str += `<img width="1024px" src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                } else {
                                    str += `<img src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                }
                            }
                            if (checkExt(file.file_name, '.mp3')) {
                                str += '<audio controls type="audio/mpeg" src="data:audio/mp3;base64,' +
                                    zipfs.arrayBufferToBase64(file.content) + '">';
                            }
                            str += '</td></tr>';
                        });
                        str += `<tr><td colspan="6" class="preview" style="overflow-x:hidden"><pre>${JSON.stringify(data, null, 2)}</pre></td></tr>`;
                        str += '</table>';
                        document.getElementById('panel').innerHTML = str;
                    });
                };
                reader.readAsArrayBuffer(this.files[0]);
            }
            function checkExt(name, ext) {
                return name.lastIndexOf(ext) === name.length - ext.length;
            }
            function log(msg) {
                document.getElementById('console').innerHTML += `<br />${msg}`; 
            }
            function clearlog() {
                document.getElementById('console').innerHTML = ''; 
            }
        }
    </script>
</body>

</html>

.rels及.xml就不顯示內容,而匯總到最後才顯示匯總的結果。網頁一開始:

https://ithelp.ithome.com.tw/upload/images/20200928/200001087Zx7QBHu17.png

後面顯示匯總的json:

https://ithelp.ithome.com.tw/upload/images/20200928/20000108hReC7JaWZn.png

https://ithelp.ithome.com.tw/upload/images/20200928/20000108xy0ahlQBYl.png

https://ithelp.ithome.com.tw/upload/images/20200928/20000108d0as6rT72T.png

其實仔細觀察,裡面還存在一些細微的差異,另外,themes底下的檔案不知道為什麼沒有匯總進來,這些就留到明天吧。


上一篇
第十二天:今天星期日,所以不工作了~~
下一篇
第十四天:兩週了的週二
系列文
中年失業大叔的耍廢日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
stephk
iT邦新手 5 級 ‧ 2020-12-03 14:48:53

謝謝分享!連續潮濕的天氣,濕氣確實令人會感到昏倦、特別累,記得定期除濕開抽濕機,屆時編程都寫得更精目、清晰,加油呀!

我要留言

立即登入留言