以下代码在OSX上的dev中运行时从未失败,但每次都在生活在Docker容器中的生产环境中失败:
DataSyncController.js
let jsonFile = await FileSystemService.ParseCsvToJson(fileName);
if (!jsonFile.success)
return res.json({ success: false });
let parsedJson = await FileSystemService.ParseJsonFile({ file: jsonFile.fileName });
if (!parsedJson.success)
return res.json({ success: false });
FileSystemService.js
static async ParseJsonFile(params)
{
return new Promise((resolve, reject) =>
{
try
{
fs.readFile(jsonFilePath, 'utf-8', (err, data) =>
{
if (err)
{
console.log('fs.readFile() error: ', err);
resolve({ success: false });
}
var file = [];
try
{
// This fails every time in the Docker container
// Error is [Unexpected end of input]
// At this point I've seend `data` evaluate to '',
// <buffer >, undefined and partial JSON data
file = JSON.parse(data);
}
catch(e)
{
console.log('ERROR parsing JSON file: ', e);
return resolve({ success: false });
}
// Do Stuff
return resolve({ success: true });
});
}
catch(exception)
{
console.error(exception);
resolve({ success: false });
}
});
}
似乎在Docker容器中,JSON文件在读取时没有写入(例如,如果我将整个JSON.parse()
块放在fs.readFile()
中,则timeout
可以正常工作并阻止它运行5秒),但我不知道这是怎么可能的,也不是为什么在Docker容器中就是这种情况,而不是在我的本地机器上。任何想法一如既往地非常感激。
更新
根据要求,这是实际将JSON文件写入磁盘的ParseCsvToJson
方法的实现。请注意,在Docker容器的开发和生产中,写入的JSON文件虽然很大(大约4,400条记录),但看起来还不错。
var Converter = require("csvtojson").Converter;
var filePath = `${config.root}/server/uploadDir`;
static async ParseCsvToJson(fileName)
{
return new Promise((resolve, reject) =>
{
try
{
let fileNameWithoutExtension = fileName.replace('.csv', '');
const jsonFilePath = `${filePath}/${fileNameWithoutExtension}.json`;
const csvFilePath = `${filePath}/${fileName}`;
// The parameter false will turn off final result construction.
// It can avoid huge memory consumption while parsing.
// The trade off is final result will not be populated to end_parsed event.
var csvConverter = new Converter({ constructResult: false, toArrayString: true });
var readStream = fs.createReadStream(csvFilePath);
var writeStream = fs.createWriteStream(jsonFilePath);
readStream.pipe(csvConverter).pipe(writeStream);
resolve({ success: true, fileName: `${fileNameWithoutExtension}.json` });
}
catch(exception)
{
console.error(exception);
resolve({ success: false });
}
});
}
答案 0 :(得分:0)
这是由于缺乏对Linux如何处理流/管道以及对csvtojson模块的文档的误解的理解。关于转换器的实例化:
var csvConverter = new Converter({ constructResult: false, toArrayString: true });
文档说:
参数false将关闭最终结果构造。 解析时可以避免大量内存消耗。 权衡是最终结果不会填充到end_parsed事件。
由于我不太了解的原因,在OSX上,这已经足够了:
var readStream = fs.createReadStream('path/to/csvfile.csv', { encoding: 'utf-8' });
var writeStream = fs.createWriteStream('path/to/jsonfile.json', { encoding: 'utf-8' });
readStream.pipe(csvConverter).pipe(writeStream);
resolve({ success: true, fileName: '.json' });
然而,在Linux系统上,文件并不总是完全写入或写入。因此,还需要以下内容:
csvConverter.on('end_parsed', () =>
{
// The docs are unclear whether there is a possible error object
// passed along here in the case of failure, but clearly mention
// that the constructed result will be unavailable, so just resolve
// the Promise
resolve({ success: true, fileName: 'jsonfile.json' });
});
这可能是一个边缘情况,但希望将来能帮助其他人。