mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-28 04:56:00 +00:00
CSV for MS Excel export
This commit is contained in:
@@ -6,6 +6,54 @@ const { getLogger } = global.DBGATE_PACKAGES['dbgate-tools'];
|
|||||||
|
|
||||||
const logger = getLogger('csvWriter');
|
const logger = getLogger('csvWriter');
|
||||||
|
|
||||||
|
class RecodeTransform extends stream.Transform {
|
||||||
|
constructor(toEncoding = 'utf8') {
|
||||||
|
super({ readableObjectMode: false, writableObjectMode: false });
|
||||||
|
this.to = String(toEncoding).toLowerCase();
|
||||||
|
this.decoder = new (global.TextDecoder || require('util').TextDecoder)('utf-8', { fatal: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
_encodeString(str) {
|
||||||
|
if (this.to === 'utf8' || this.to === 'utf-8') {
|
||||||
|
return Buffer.from(str, 'utf8');
|
||||||
|
}
|
||||||
|
if (this.to === 'utf16le' || this.to === 'ucs2' || this.to === 'utf-16le') {
|
||||||
|
return Buffer.from(str, 'utf16le');
|
||||||
|
}
|
||||||
|
if (this.to === 'utf16be' || this.to === 'utf-16be') {
|
||||||
|
const le = Buffer.from(str, 'utf16le');
|
||||||
|
for (let i = 0; i + 1 < le.length; i += 2) {
|
||||||
|
const a = le[i];
|
||||||
|
le[i] = le[i + 1];
|
||||||
|
le[i + 1] = a;
|
||||||
|
}
|
||||||
|
return le;
|
||||||
|
}
|
||||||
|
throw new Error(`Unsupported target encoding: ${this.to}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
_transform(chunk, enc, cb) {
|
||||||
|
try {
|
||||||
|
if (!Buffer.isBuffer(chunk)) chunk = Buffer.from(chunk, enc);
|
||||||
|
const part = this.decoder.decode(chunk, { stream: true });
|
||||||
|
if (part.length) this.push(this._encodeString(part));
|
||||||
|
cb();
|
||||||
|
} catch (e) {
|
||||||
|
cb(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_flush(cb) {
|
||||||
|
try {
|
||||||
|
const rest = this.decoder.decode();
|
||||||
|
if (rest.length) this.push(this._encodeString(rest));
|
||||||
|
cb();
|
||||||
|
} catch (e) {
|
||||||
|
cb(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CsvPrepareStream extends stream.Transform {
|
class CsvPrepareStream extends stream.Transform {
|
||||||
constructor({ header }) {
|
constructor({ header }) {
|
||||||
super({ objectMode: true });
|
super({ objectMode: true });
|
||||||
@@ -26,18 +74,59 @@ class CsvPrepareStream extends stream.Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writer({ fileName, encoding = 'utf-8', header = true, delimiter, quoted }) {
|
async function writer({
|
||||||
|
fileName,
|
||||||
|
encoding = 'utf-8',
|
||||||
|
header = true,
|
||||||
|
delimiter,
|
||||||
|
quoted,
|
||||||
|
writeBom,
|
||||||
|
writeSepHeader,
|
||||||
|
recordDelimiter,
|
||||||
|
}) {
|
||||||
logger.info(`DBGM-00133 Writing file ${fileName}`);
|
logger.info(`DBGM-00133 Writing file ${fileName}`);
|
||||||
const csvPrepare = new CsvPrepareStream({ header });
|
const csvPrepare = new CsvPrepareStream({ header });
|
||||||
const csvStream = csv.stringify({ delimiter, quoted });
|
const csvStream = csv.stringify({ delimiter, quoted, record_delimiter: recordDelimiter });
|
||||||
const fileStream = fs.createWriteStream(fileName, encoding);
|
const fileStream = fs.createWriteStream(fileName, encoding);
|
||||||
// csvPrepare.pipe(csvStream);
|
if (writeBom) {
|
||||||
// csvStream.pipe(fileStream);
|
switch (encoding.toLowerCase()) {
|
||||||
// csvPrepare['finisher'] = fileStream;
|
case 'utf-8':
|
||||||
|
case 'utf8':
|
||||||
|
fileStream.write(Buffer.from([0xef, 0xbb, 0xbf]));
|
||||||
|
break;
|
||||||
|
case 'utf-16':
|
||||||
|
case 'utf16':
|
||||||
|
fileStream.write(Buffer.from([0xff, 0xfe]));
|
||||||
|
break;
|
||||||
|
case 'utf-16le':
|
||||||
|
case 'utf16le':
|
||||||
|
fileStream.write(Buffer.from([0xff, 0xfe]));
|
||||||
|
break;
|
||||||
|
case 'utf-16be':
|
||||||
|
case 'utf16be':
|
||||||
|
fileStream.write(Buffer.from([0xfe, 0xff]));
|
||||||
|
break;
|
||||||
|
case 'utf-32le':
|
||||||
|
case 'utf32le':
|
||||||
|
fileStream.write(Buffer.from([0xff, 0xfe, 0x00, 0x00]));
|
||||||
|
break;
|
||||||
|
case 'utf-32be':
|
||||||
|
case 'utf32be':
|
||||||
|
fileStream.write(Buffer.from([0x00, 0x00, 0xfe, 0xff]));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (writeSepHeader) {
|
||||||
|
fileStream.write(`sep=${delimiter}${recordDelimiter || '\n'}`);
|
||||||
|
}
|
||||||
|
|
||||||
csvPrepare.requireFixedStructure = true;
|
csvPrepare.requireFixedStructure = true;
|
||||||
|
|
||||||
return [csvPrepare, csvStream, fileStream];
|
return encoding.toLowerCase() === 'utf8' || encoding.toLowerCase() === 'utf-8'
|
||||||
// return csvPrepare;
|
? [csvPrepare, csvStream, fileStream]
|
||||||
|
: [csvPrepare, csvStream, new RecodeTransform(encoding), fileStream];
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = writer;
|
module.exports = writer;
|
||||||
|
|||||||
@@ -68,5 +68,31 @@ export default {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'CSV file for MS Excel',
|
||||||
|
extension: 'csv',
|
||||||
|
createWriter: (fileName) => ({
|
||||||
|
functionName: 'writer@dbgate-plugin-csv',
|
||||||
|
props: {
|
||||||
|
fileName,
|
||||||
|
delimiter: ';',
|
||||||
|
recordDelimiter: '\r\n',
|
||||||
|
encoding: 'utf16le',
|
||||||
|
writeSepHeader: true,
|
||||||
|
writeBom: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'TSV file (tab separated)',
|
||||||
|
extension: 'tsv',
|
||||||
|
createWriter: (fileName) => ({
|
||||||
|
functionName: 'writer@dbgate-plugin-csv',
|
||||||
|
props: {
|
||||||
|
fileName,
|
||||||
|
delimiter: '\t',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user