Fb2Helper.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. const fs = require('fs-extra');
  2. const iconv = require('iconv-lite');
  3. const textUtils = require('./textUtils');
  4. const Fb2Parser = require('../fb2/Fb2Parser');
  5. const utils = require('../utils');
  6. class Fb2Helper {
  7. checkEncoding(data) {
  8. //Корректируем кодировку UTF-16
  9. let encoding = textUtils.getEncoding(data);
  10. if (encoding.indexOf('UTF-16') == 0) {
  11. data = Buffer.from(iconv.decode(data, encoding));
  12. encoding = 'utf-8';
  13. }
  14. //Корректируем пробелы, всякие файлы попадаются :(
  15. if (data[0] == 32) {
  16. data = Buffer.from(data.toString().trim());
  17. }
  18. //Окончательно корректируем кодировку
  19. let result = data;
  20. let left = data.indexOf('<?xml version="1.0"');
  21. if (left < 0) {
  22. left = data.indexOf('<?xml version=\'1.0\'');
  23. }
  24. if (left >= 0) {
  25. const right = data.indexOf('?>', left);
  26. if (right >= 0) {
  27. const head = data.slice(left, right + 2).toString();
  28. const m = head.match(/encoding=['"](.*?)['"]/);
  29. if (m) {
  30. let enc = m[1].toLowerCase();
  31. if (enc != 'utf-8') {
  32. //если кодировка не определена в getEncoding, используем enc
  33. if (encoding.indexOf('ISO-8859') >= 0) {
  34. encoding = enc;
  35. }
  36. result = iconv.decode(data, encoding);
  37. result = Buffer.from(result.toString().replace(m[0], `encoding="utf-8"`));
  38. }
  39. }
  40. }
  41. }
  42. return result;
  43. }
  44. async getDescAndCover(bookFile) {
  45. let data = await fs.readFile(bookFile);
  46. data = await utils.gunzipBuffer(data);
  47. data = this.checkEncoding(data);
  48. const parser = new Fb2Parser();
  49. parser.fromString(data.toString(), {
  50. lowerCase: true,
  51. pickNode: route => route.indexOf('fictionbook/body') !== 0,
  52. });
  53. const coverImage = parser.$$('/description/title-info/coverpage/image');
  54. let cover = null;
  55. let coverExt = '';
  56. if (coverImage.count) {
  57. const coverAttrs = coverImage.attrs();
  58. const href = coverAttrs[`${parser.xlinkNS}:href`];
  59. if (href) {
  60. const binaryId = (href[0] == '#' ? href.substring(1) : href);
  61. //найдем нужный image
  62. for (const node of parser.$$array('/binary')) {
  63. let attrs = node.attrs();
  64. if (!attrs)
  65. return;
  66. if (attrs.id === binaryId) {
  67. let coverType = attrs['content-type'];
  68. coverType = (coverType == 'image/jpg' || coverType == 'application/octet-stream' ? 'image/jpeg' : coverType);
  69. coverExt = (coverType == 'image/png' ? '.png' : '.jpg');
  70. const base64 = node.text();
  71. cover = (base64 ? Buffer.from(base64, 'base64') : null);
  72. }
  73. }
  74. }
  75. }
  76. parser.remove('binary');
  77. return {fb2: parser, cover, coverExt};
  78. }
  79. }
  80. module.exports = Fb2Helper;