add encoding support to file in/out node (#2066)

* add encoding support to file in/out node

* update package.json

* change default encoding label: 'none' -> 'utf8[default]'

* add a missing message catalogue entry

* change default encoding label
This commit is contained in:
Hiroyasu Nishiyama
2019-03-07 07:28:33 +09:00
committed by Dave Conway-Jones
parent 3c013b3533
commit dc89218702
9 changed files with 1012 additions and 14 deletions

View File

@@ -22,6 +22,11 @@
<input type="checkbox" id="node-input-createDir" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-createDir" style="width: 70%;"><span data-i18n="file.label.createdir"></span></label>
</div>
<div class="form-row">
<label for="node-input-encoding"><i class="fa fa-flag"></i> <span data-i18n="file.label.encoding"></span></label>
<select type="text" id="node-input-encoding" style="width: 250px;">
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
@@ -48,6 +53,11 @@
<input type="checkbox" id="node-input-sendError" style="width:auto">
<label style="width:auto; margin-bottom:0; vertical-align: middle;" for="node-input-sendError" data-i18n="file.label.sendError"></label>
</div>
<div class="form-row" id="encoding-spec">
<label for="node-input-encoding"><i class="fa fa-flag"></i> <span data-i18n="file.label.encoding"></span></label>
<select type="text" id="node-input-encoding" style="width: 250px;">
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
@@ -56,6 +66,132 @@
</script>
<script type="text/javascript">
(function(){
var encodings = [
[ "file.encoding.native",
"utf8",
"ucs2",
"utf-16le",
"ascii",
"binary",
"base64",
"hex"
],
[ "file.encoding.unicode",
"utf-16be",
],
[ "file.encoding.japanese",
"Shift_JIS",
"Windows-31j",
"Windows932",
"EUC-JP"
],
[ "file.encoding.chinese",
"GB2312",
"GBK",
"GB18030",
"Windows936",
"EUC-CN"
],
[ "file.encoding.korean",
"KS_C_5601",
"Windows949",
"EUC-KR"
],
[ "file.encoding.taiwan",
"Big5",
"Big5-HKSCS",
"Windows950"
],
[ "file.encoding.windows",
"cp874",
"cp1250",
"cp1251",
"cp1252",
"cp1253",
"cp1254",
"cp1255",
"cp1256",
"cp1257",
"cp1258"
],
[ "file.encoding.iso",
"ISO-8859-1",
"ISO-8859-2",
"ISO-8859-3",
"ISO-8859-4",
"ISO-8859-5",
"ISO-8859-6",
"ISO-8859-7",
"ISO-8859-8",
"ISO-8859-9",
"ISO-8859-10",
"ISO-8859-11",
"ISO-8859-12",
"ISO-8859-13",
"ISO-8859-14",
"ISO-8859-15",
"ISO-8859-16"
],
[ "file.encoding.ibm",
"cp437",
"cp737",
"cp775",
"cp808",
"cp850",
"cp852",
"cp855",
"cp856",
"cp857",
"cp858",
"cp860",
"cp861",
"cp866",
"cp869",
"cp922",
"cp1046",
"cp1124",
"cp1125",
"cp1129",
"cp1133",
"cp1161",
"cp1162",
"cp1163"
],
[ "file.encoding.mac",
"maccroatian",
"maccyrillic",
"macgreek",
"maciceland",
"macroman",
"macromania",
"macthai",
"macturkish",
"macukraine",
"maccenteuro",
"macintosh"
],
[ "file.encoding.koi8",
"koi8-r",
"koi8-u",
"koi8-ru",
"koi8-t"
],
[ "file.encoding.misc",
"armscii8",
"rk1048",
"tcvn",
"georgianacademy",
"georgianps",
"pt154",
"viscii",
"iso646cn",
"iso646jp",
"hproman8",
"tis620"
]
];
RED.nodes.registerType('file',{
category: 'storage-output',
defaults: {
@@ -63,7 +199,8 @@
filename: {value:""},
appendNewline: {value:true},
createDir: {value:false},
overwriteFile: {value:"false"}
overwriteFile: {value:"false"},
encoding: {value:"none"}
},
color:"BurlyWood",
inputs:1,
@@ -80,6 +217,33 @@
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var node = this;
var encSel = $("#node-input-encoding");
$("<option/>", {
value: "none",
label: node._("file.encoding.none")
}).appendTo(encSel);
encodings.forEach(function(item) {
if(Array.isArray(item)) {
var group = $("<optgroup/>", {
label: node._(item[0])
}).appendTo(encSel);
for (var i = 1; i < item.length; i++) {
var enc = item[i];
$("<option/>", {
value: enc,
label: enc
}).appendTo(group);
}
}
else {
$("<option/>", {
value: item,
label: item
}).appendTo(encSel);
}
});
encSel.val(node.encoding);
$("#node-input-overwriteFile").on("change",function() {
if (this.value === "delete") { $(".form-row-file-write-options").hide(); }
else { $(".form-row-file-write-options").show(); }
@@ -94,7 +258,8 @@
filename: {value:""},
format: {value:"utf8"},
chunk: {value:false},
sendError: {value: false}
sendError: {value: false},
encoding: {value: "none"}
},
color:"BurlyWood",
inputs:1,
@@ -110,19 +275,46 @@
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var node = this;
var encSel = $("#node-input-encoding");
$("<option/>", {
value: "none",
label: node._("file.encoding.none")
}).appendTo(encSel);
encodings.forEach(function(item) {
if(Array.isArray(item)) {
var group = $("<optgroup/>", {
label: node._(item[0])
}).appendTo(encSel);
for (var i = 1; i < item.length; i++) {
var enc = item[i];
$("<option/>", {
value: enc,
label: enc
}).appendTo(group);
}
}
else {
$("<option/>", {
value: item,
label: item
}).appendTo(encSel);
}
});
encSel.val(node.encoding);
if (this.sendError === undefined) {
$("#node-input-sendError").prop("checked",true);
}
$("#node-input-format").on("change",function() {
if ($("#node-input-format").val() === "utf8") {
$("#buffer-input-type").hide();
$("#line-input-type").show();
var format = $("#node-input-format").val();
if ((format === "utf8") || (format === "lines")) {
$("#encoding-spec").show();
}
else {
$("#buffer-input-type").show();
$("#line-input-type").hide();
$("#encoding-spec").hide();
}
});
}
});
})();
</script>

View File

@@ -19,13 +19,29 @@ module.exports = function(RED) {
var fs = require("fs-extra");
var os = require("os");
var path = require("path");
var iconv = require("iconv-lite")
function encode(data, enc) {
if (enc !== "none") {
return iconv.encode(data, enc);
}
return Buffer.from(data);
}
function decode(data, enc) {
if (enc !== "none") {
return iconv.decode(data, enc);
}
return data.toString();
}
function FileNode(n) {
RED.nodes.createNode(this,n);
this.filename = n.filename;
this.appendNewline = n.appendNewline;
this.overwriteFile = n.overwriteFile.toString();
this.createDir = n.createDir || false;
this.encoding = n.encoding || "none";
var node = this;
node.wstream = null;
node.msgQueue = [];
@@ -75,7 +91,7 @@ module.exports = function(RED) {
if (typeof data === "boolean") { data = data.toString(); }
if (typeof data === "number") { data = data.toString(); }
if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; }
var buf = Buffer.from(data);
var buf = encode(data, node.encoding);
if (node.overwriteFile === "true") {
var wstream = fs.createWriteStream(filename, { encoding:'binary', flags:'w', autoClose:true });
node.wstream = wstream;
@@ -222,6 +238,7 @@ module.exports = function(RED) {
this.filename = n.filename;
this.format = n.format;
this.chunk = false;
this.encoding = n.encoding || "none";
if (n.sendError === undefined) {
this.sendError = true;
} else {
@@ -261,7 +278,7 @@ module.exports = function(RED) {
if (node.chunk === true) {
getout = true;
if (node.format === "lines") {
spare += chunk.toString();
spare += decode(chunk, node.encoding);
var bits = spare.split("\n");
for (var i=0; i < bits.length - 1; i++) {
var m = {
@@ -306,7 +323,9 @@ module.exports = function(RED) {
})
.on('end', function() {
if (node.chunk === false) {
if (node.format === "utf8") { msg.payload = lines.toString(); }
if (node.format === "utf8") {
msg.payload = decode(lines, node.encoding);
}
else { msg.payload = lines; }
node.send(msg);
}