electronFilesWorker.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. const fs = require('fs');
  2. const path = require('path');
  3. const { COPYFILE_EXCL } = fs.constants;
  4. function isConflict(origStat, stat)
  5. {
  6. return stat != null && origStat != null && stat.mtimeMs != origStat.mtimeMs;
  7. };
  8. function saveFile(fileObject, data, origStat, overwrite, defEnc, reqId)
  9. {
  10. var retryCount = 0;
  11. var backupCreated = false;
  12. var writeFile = function()
  13. {
  14. if (data == null || data.length == 0)
  15. {
  16. postMessage({error: true, msg: 'empty data', reqId: reqId});
  17. }
  18. else
  19. {
  20. var writeEnc = defEnc || fileObject.encoding;
  21. fs.writeFile(fileObject.path, data, writeEnc,
  22. function (e)
  23. {
  24. if (e)
  25. {
  26. postMessage({error: true, msg: 'saving failed', e: e, reqId: reqId});
  27. }
  28. else
  29. {
  30. fs.stat(fileObject.path, function(e2, stat2)
  31. {
  32. if (e2)
  33. {
  34. postMessage({error: true, msg: 'stat failed', e: e2, reqId: reqId});
  35. }
  36. else
  37. {
  38. // Workaround for possible writing errors is to check the written
  39. // contents of the file and retry 3 times before showing an error
  40. fs.readFile(fileObject.path, writeEnc, (err, writtenData) =>
  41. {
  42. if (data != writtenData)
  43. {
  44. retryCount++;
  45. if (retryCount < 3)
  46. {
  47. writeFile();
  48. }
  49. else
  50. {
  51. postMessage({error: true, msg: 'all saving trials failed', e: e, reqId: reqId});
  52. }
  53. }
  54. else
  55. {
  56. postMessage({success: true, data: {stat: stat2}, reqId: reqId});
  57. if (backupCreated)
  58. {
  59. fs.unlink(fileObject.bkpPath, (err) => {}); //Ignore errors!
  60. }
  61. }
  62. });
  63. }
  64. });
  65. }
  66. });
  67. }
  68. };
  69. function doSaveFile()
  70. {
  71. //Copy file to backup file (after conflict and stat is checked)
  72. fs.copyFile(fileObject.path, fileObject.bkpPath, COPYFILE_EXCL, (err) =>
  73. {
  74. if (!err)
  75. {
  76. backupCreated = true;
  77. }
  78. writeFile();
  79. });
  80. };
  81. if (overwrite)
  82. {
  83. doSaveFile();
  84. }
  85. else
  86. {
  87. //TODO Using stat before write is not recommended, we can check the error code from writeFile
  88. fs.stat(fileObject.path, function(err, stat)
  89. {
  90. if (isConflict(origStat, stat))
  91. {
  92. postMessage({error: true, msg: 'conflict', e: {isConflicted: true}, reqId: reqId});
  93. }
  94. else if (err != null && err.code !== 'ENOENT')
  95. {
  96. postMessage({error: true, msg: 'stat failed', e: err, reqId: reqId});
  97. }
  98. else
  99. {
  100. doSaveFile();
  101. }
  102. });
  103. }
  104. };
  105. //TODO handle reqId better
  106. onmessage = function(e)
  107. {
  108. switch(e.data.action)
  109. {
  110. case 'saveFile':
  111. saveFile(e.data.fileObject, e.data.data, e.data.origStat, e.data.overwrite, e.data.defEnc, e.data.reqId);
  112. break;
  113. };
  114. };