server.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. const fs = require('fs')
  2. const asfs = require('asfs')
  3. const express = require('express')
  4. const multer = require('multer')
  5. const childProcess = require('child_process')
  6. const bodyParser = require('body-parser')
  7. const pdf2htmlexPath = `${__dirname}/node_modules/@alancnet/pdf2htmlex/bin-win/pdf2htmlEX.exe`
  8. const phantom = require('phantom')
  9. const uuid = require('uuid')
  10. const parseDataUrl = require('data-urls')
  11. const cors = require('cors')
  12. const upload = multer({
  13. dest: 'temp/'
  14. })
  15. const app = express()
  16. app.use(cors({
  17. origin: '*'
  18. }))
  19. app.use(bodyParser.urlencoded({extended: false, limit: '100mb'}))
  20. app.use(express.static('./public'))
  21. app.post('/edit', upload.single('document'), async (req, res) => {
  22. let pdfFile, htmlFile
  23. if (req.file) {
  24. pdfFile = req.file.path
  25. htmlFile = `${req.file.path}.html`
  26. } else if (req.body.url) {
  27. pdfFile = `temp/${uuid()}.pdf`
  28. htmlFile = `${pdfFile}.html`
  29. const pdf = parseDataUrl(req.body.url)
  30. await asfs.writeFileAsync(pdfFile, pdf.body)
  31. }
  32. /*
  33. Executes pdf2htmlex[.exe] with:
  34. - 200 horizontal and vertical DPI
  35. - TrueType Font format (because woff does not render in PhantomJS)
  36. - No DRM, overriding any PDF settings forbidding copying or modifying
  37. - The path to the source PDF file
  38. - The path to the output HTML file
  39. */
  40. childProcess.exec(`"${pdf2htmlexPath}" --hdpi 200 --vdpi 200 --font-format ttf --no-drm 1 "${pdfFile}" "${htmlFile}"`, (err, stdout, stderr) => {
  41. if (err) {
  42. res.status(500).send(`<pre>${err}\n\n${stdout}\n\n${stderr}</pre>`)
  43. } else {
  44. fs.readFile('public/edit.html', (err, editHtml) => {
  45. fs.readFile(htmlFile, 'utf8', (err, data) => {
  46. if (err) {
  47. res.status(500).send(`<pre>${err}\n\n${stdout}\n\n${stderr}</pre>`)
  48. } else {
  49. res.status(200).send(data.replace('</body>', `${editHtml}</body>`))
  50. }
  51. fs.unlink(pdfFile)
  52. fs.unlink(htmlFile)
  53. })
  54. })
  55. }
  56. })
  57. })
  58. app.post('/save', (req, res) => {
  59. console.log(req.body.html)
  60. const tmpUuid = uuid()
  61. const htmlPath = `temp/${tmpUuid}.html`
  62. const pdfPath = `temp/${tmpUuid}.pdf`
  63. const pageWidth = /\.w0{width:([\d\.]*)pt/.exec(req.body.html)[1]
  64. const pageHeight = /\.h0{height:([\d\.]*)pt/.exec(req.body.html)[1]
  65. fs.writeFile(htmlPath, req.body.html, 'utf8', async (err) => {
  66. const instance = await phantom.create()
  67. const page = await instance.createPage()
  68. page.property('paperSize', {
  69. width: pageWidth,
  70. height: pageHeight,
  71. margin: '0px'
  72. })
  73. page.open(htmlPath)
  74. page.on('onLoadFinished', function(status) {
  75. if (status === 'success') {
  76. page.render(pdfPath, {format: 'pdf'})
  77. setTimeout(() => {
  78. res.download(pdfPath, 'todo-preserve-filename.pdf', (err) => {
  79. if (err) {
  80. console.error(err)
  81. res.status(500).send(err)
  82. }
  83. //fs.unlink(htmlPath)
  84. //fs.unlink(pdfPath)
  85. })
  86. }, 5000)
  87. } else {
  88. res.status(500).send('Failed: ' + status)
  89. }
  90. })
  91. })
  92. })
  93. app.listen(process.env.PORT || 3000)