convert.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. # -*- coding: utf-8 -*-
  2. from .__load__ import *
  3. class Convert(object):
  4. def crearSignature():
  5. num = Demeter.time() - 3600*24
  6. model = Demeter.model('signature')
  7. model.cdate.assign(num, exp='<=')
  8. model.delete()
  9. def signature(self, site_id, appid, appsecret, timestamp, nonce, file, file_id, uid):
  10. sign = Demeter.sha1(appid + '&' + appsecret + '&' + str(timestamp) + '&' + str(nonce) + '&' + file + '&' + str(file_id) + '&' + str(uid));
  11. time = Demeter.time()
  12. num = 3600*12
  13. if time - timestamp > num:
  14. return False
  15. # sign 只能使用一次
  16. model = Demeter.model('signature')
  17. model.signature = sign
  18. model.site_id = site_id
  19. info = model.select(type='fetchone')
  20. if info:
  21. return False
  22. param = {}
  23. param['signature'] = sign
  24. param['appid'] = appid
  25. param['appsecret'] = appsecret
  26. param['timestamp'] = timestamp
  27. param['nonce'] = nonce
  28. param['file'] = file
  29. param['file_id'] = file_id
  30. param['uid'] = uid
  31. model.signature = sign
  32. model.site_id = site_id
  33. model.insert()
  34. return param
  35. def update(self, site, appid, file, file_id, file_type, uid):
  36. info = self.getFile(appid, file)
  37. convert = Demeter.model('convert')
  38. convert.site_id = site
  39. convert.key = info['key']
  40. data = convert.select(type='fetchone')
  41. if not data:
  42. convert.site_id = site
  43. convert.uid = uid
  44. convert.file_id = file_id
  45. convert.file_type = file_type
  46. convert.file_size = 0
  47. convert.file = info['file']
  48. convert.key = info['key']
  49. convert.name = info['name']
  50. convert.ext = info['ext']
  51. convert.local = info['local']
  52. convert.path = info['path']
  53. convert.pdf = info['pdf']
  54. convert.html = info['html']
  55. convert.url = info['url']
  56. id = convert.insert()
  57. info['status'] = 1
  58. info['id'] = id
  59. else:
  60. info['id'] = data['id']
  61. info['status'] = data['status']
  62. if uid:
  63. self.auth(site, uid, info['id'], 1)
  64. return info
  65. def getAuth(self, site, uid, convert_id):
  66. user = Demeter.model('user')
  67. user.uid = uid
  68. user.site_id = site
  69. user.convert_id = convert_id
  70. data = user.select(type='fetchone')
  71. return data
  72. def auth(self, site, uid, convert_id, status):
  73. user = Demeter.model('user')
  74. user.uid = uid
  75. user.site_id = site
  76. user.convert_id = convert_id
  77. data = user.select(type='fetchone')
  78. if not data:
  79. user.site_id = site
  80. user.uid = uid
  81. user.convert_id = convert_id
  82. user.status = status
  83. user.insert()
  84. elif data['status'] != status:
  85. # 适用于文档转让
  86. user.id = data['id']
  87. update = {}
  88. update['status'] = status
  89. user.update(update)
  90. return True
  91. def getFile(self, appid, file):
  92. info = {}
  93. (filepath,temp) = os.path.split(file)
  94. (filename,extension) = os.path.splitext(temp)
  95. info['file'] = file
  96. info['key'] = self.getKey(appid, file)
  97. info['ext'] = extension
  98. info['name'] = filename
  99. info = self.getLocalFile(appid, file, info)
  100. return info
  101. def getLocalFile(self, appid, file, info):
  102. day = str(date.today())
  103. day = day.split('-')
  104. #filename = Demeter.md5(str(uuid.uuid5(uuid.uuid1(), info['key'])))
  105. filename = info['key']
  106. filepath = str(appid) + '/' + day[0] + '/' + day[1] + '/' + day[2]
  107. filepath = File.mkdirs(os.path.join(Demeter.path, 'runtime','files', filepath)) + '/' + filename
  108. local = filepath + info['ext']
  109. info['local'] = local
  110. info['pdf'] = filepath + '/' + filename + '.pdf'
  111. # 这里要增加权限控制 html不能直接访问
  112. info['html'] = filepath + '/' + filename + '.html'
  113. info['url'] = info['html'].replace(Demeter.path + 'runtime', '')
  114. info['path'] = filepath + '/'
  115. return info
  116. if File.exists(local):
  117. return info
  118. else:
  119. self.download(file, local);
  120. return info
  121. def download(self, file, local):
  122. if 'http' in file:
  123. import requests
  124. r = requests.get(file, stream=True)
  125. with open(local, 'wb') as up:
  126. for chunk in r.iter_content(chunk_size=1024):
  127. if chunk:
  128. up.write(chunk)
  129. else:
  130. import shutil
  131. shutil.copyfile(file, local)
  132. if File.exists(local):
  133. return True
  134. return False
  135. def command(self, info):
  136. File.mkdir(info['path'])
  137. convert = 'cd ' + info['path'] + ' && '
  138. if info['ext'] != '.pdf':
  139. convert = convert + 'libreoffice --invisible --convert-to pdf ' + info['local']
  140. convert = convert + ' && '
  141. else:
  142. info['pdf'] = info['local']
  143. convert = convert + 'pdf2htmlEX --zoom 1.3 --no-drm 1 --split-pages 1 '
  144. convert = convert + '--embed-css 1 --embed-javascript 0 --embed-image 0 --embed-font 1 --process-outline 0 '
  145. convert = convert + '--embed-external-font 0 --dest-dir '+info['path']+' --page-filename %d.page ' + info['pdf']
  146. return convert
  147. def total(self, path):
  148. page = 0
  149. for parentdir,dirname,filenames in os.walk(path):
  150. for filename in filenames:
  151. if os.path.splitext(filename)[1]=='.page':
  152. page = page + 1
  153. return page
  154. def handle(self, id):
  155. model = Demeter.model('convert')
  156. model.id = id
  157. info = model.select(type='fetchone')
  158. if not info:
  159. return
  160. siteModel = Demeter.model('site')
  161. siteModel.id = info['site_id']
  162. site = siteModel.select(type='fetchone')
  163. status = True
  164. if info['status'] == 1 or info['status'] == 4:
  165. status = False
  166. if info and status == False:
  167. model.id = id
  168. update = {}
  169. update['status'] = 2
  170. model.update(update)
  171. if not File.exists(info['local']):
  172. self.download(info['file'], info['local'])
  173. if not File.exists(info['html']):
  174. #if info:
  175. handle = self.command(info)
  176. Shell.popen(handle)
  177. if File.exists(info['html']):
  178. # 截屏
  179. self.cut(info)
  180. #self.string_switch(info['html'], "taste", "tasting")
  181. # 获取有多少页
  182. page = self.total(info['path'])
  183. model.id = id
  184. size = os.path.getsize(info['local'])
  185. update = {}
  186. update['file_size'] = size
  187. update['page'] = page
  188. update['status'] = 3
  189. model.update(update)
  190. # 通知接口 通知应用成功转换
  191. info['page'] = page
  192. info['file_size'] = size
  193. self.api(info, site)
  194. return
  195. model.id = id
  196. update = {}
  197. update['status'] = 4
  198. model.update(update)
  199. def api(self, info, site):
  200. if 'file_id' in info and info['file_id']:
  201. api = site['api']
  202. appid = site['appid']
  203. appsecret = site['appsecret']
  204. timestamp = Demeter.time()
  205. nonce = Demeter.nonce()
  206. file = info['key']
  207. file_id = info['file_id']
  208. uid = info['uid']
  209. param = self.signature(site['id'], appid, appsecret, timestamp, nonce, file, file_id, uid)
  210. param['url'] = 'main/view'
  211. param['img'] = info['url'] + '.jpg'
  212. param['page'] = info['page']
  213. param['ext'] = info['ext']
  214. param['file_size'] = info['file_size']
  215. Demeter.curl(api, param, 'post')
  216. def cut(self, info):
  217. pdf = Image(filename=info['pdf'], resolution=50)
  218. jpg = pdf.convert('jpg')
  219. req_image = []
  220. i = 0
  221. for img in jpg.sequence:
  222. if i == 0:
  223. img_page = Image(image=img)
  224. req_image.append(img_page.make_blob('jpg'))
  225. i = i+1
  226. dest = info['html']
  227. for img in req_image:
  228. ff = open(dest + '.jpg','wb')
  229. ff.write(img)
  230. ff.close()
  231. def string_switch(self, x,y,z,s=1):
  232. with open(x, "r", encoding="utf-8") as f:
  233. #readlines以列表的形式将文件读出
  234. lines = f.readlines()
  235. with open(x, "w", encoding="utf-8") as f_w:
  236. #定义一个数字,用来记录在读取文件时在列表中的位置
  237. n = 0
  238. #默认选项,只替换第一次匹配到的行中的字符串
  239. if s == 1:
  240. for line in lines:
  241. if y in line:
  242. line = line.replace(y,z)
  243. f_w.write(line)
  244. n += 1
  245. break
  246. f_w.write(line)
  247. n += 1
  248. #将剩余的文本内容继续输出
  249. for i in range(n,len(lines)):
  250. f_w.write(lines[i])
  251. #全局匹配替换
  252. elif s == 'g':
  253. for line in lines:
  254. if y in line:
  255. line = line.replace(y,z)
  256. f_w.write(line)