convert.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. # -*- coding: utf-8 -*-
  2. from __future__ import division
  3. from .__load__ import *
  4. class Convert(object):
  5. def crearSignature(self):
  6. num = Demeter.time() - 3600*24
  7. model = Demeter.model('signature')
  8. model.cdate.assign(num, exp='<=')
  9. model.delete()
  10. def signature(self, site_id, appid, appsecret, timestamp, nonce, file, file_id, uid, status = 1):
  11. sign = Demeter.sha1(appid + '&' + appsecret + '&' + str(timestamp) + '&' + str(nonce) + '&' + file + '&' + str(file_id) + '&' + str(uid));
  12. time = Demeter.time()
  13. num = 3600*12
  14. if time - int(timestamp) > num:
  15. return False
  16. # sign 只能使用一次
  17. if status < 10:
  18. model = Demeter.model('signature')
  19. model.signature = sign
  20. model.site_id = site_id
  21. info = model.select(type='fetchone')
  22. if info:
  23. return False
  24. param = {}
  25. param['signature'] = sign
  26. param['appid'] = appid
  27. param['appsecret'] = appsecret
  28. param['timestamp'] = timestamp
  29. param['nonce'] = nonce
  30. param['file'] = file
  31. param['file_id'] = file_id
  32. param['uid'] = uid
  33. if status < 10:
  34. model.signature = sign
  35. model.site_id = site_id
  36. model.insert()
  37. return param
  38. def update(self, site, appid, file, file_id, file_type, uid):
  39. info = self.getFile(appid, file)
  40. convert = Demeter.model('convert')
  41. convert.site_id = site
  42. convert.key = info['key']
  43. data = convert.select(type='fetchone')
  44. if not data:
  45. convert.site_id = site
  46. convert.uid = uid
  47. convert.file_id = file_id
  48. convert.file_type = file_type
  49. convert.file_size = 0
  50. convert.file = info['file']
  51. convert.key = info['key']
  52. convert.name = info['name']
  53. convert.ext = info['ext']
  54. convert.local = info['local']
  55. convert.path = info['path']
  56. convert.pdf = info['pdf']
  57. convert.html = info['html']
  58. convert.url = info['url']
  59. id = convert.insert()
  60. info['status'] = 1
  61. info['id'] = id
  62. else:
  63. info['id'] = data['id']
  64. info['status'] = data['status']
  65. if uid:
  66. self.auth(site, uid, info['id'], 1)
  67. return info
  68. def getAuth(self, site, uid, convert_id):
  69. user = Demeter.model('user')
  70. user.uid = uid
  71. user.site_id = site
  72. user.convert_id = convert_id
  73. data = user.select(type='fetchone')
  74. return data
  75. def auth(self, site, uid, convert_id, status):
  76. user = Demeter.model('user')
  77. user.uid = uid
  78. user.site_id = site
  79. user.convert_id = convert_id
  80. data = user.select(type='fetchone')
  81. if not data:
  82. user.site_id = site
  83. user.uid = uid
  84. user.convert_id = convert_id
  85. user.status = status
  86. user.insert()
  87. elif data['status'] != status:
  88. # 适用于文档转让
  89. user.id = data['id']
  90. update = {}
  91. update['status'] = status
  92. user.update(update)
  93. return True
  94. def get(self, site, appid, file):
  95. convert = Demeter.model('convert')
  96. convert.site_id = site
  97. #convert.key = self.getKey(appid, file)
  98. convert.key = file
  99. data = convert.select(type='fetchone')
  100. return data
  101. def getKey(self, appid, file):
  102. return Demeter.sha1(str(appid) + '_' + str(file))
  103. def getFile(self, appid, file):
  104. info = {}
  105. (filepath,temp) = os.path.split(file)
  106. (filename,extension) = os.path.splitext(temp)
  107. info['file'] = file
  108. info['key'] = self.getKey(appid, file)
  109. info['ext'] = extension
  110. info['name'] = filename
  111. info = self.getLocalFile(appid, file, info)
  112. return info
  113. def getLocalFile(self, appid, file, info):
  114. day = str(date.today())
  115. day = day.split('-')
  116. #filename = Demeter.md5(str(uuid.uuid5(uuid.uuid1(), info['key'])))
  117. filename = info['key']
  118. filepath = str(appid) + '/' + day[0] + '/' + day[1] + '/' + day[2]
  119. path = ''
  120. if 'save' in Demeter.config['setting']:
  121. filepath = File.mkdirs(os.path.join(Demeter.config['setting']['save'], filepath)) + '/' + filename
  122. else:
  123. filepath = File.mkdirs(os.path.join(Demeter.path, 'runtime','files', filepath)) + '/' + filename
  124. local = filepath + info['ext']
  125. info['local'] = local
  126. info['pdf'] = filepath + '/' + filename + '.pdf'
  127. # 这里要增加权限控制 html不能直接访问
  128. info['html'] = filepath + '/' + filename + '.html'
  129. info['url'] = info['html'].replace(Demeter.path + 'runtime', '')
  130. info['path'] = filepath + '/'
  131. return info
  132. if File.exists(local):
  133. return info
  134. else:
  135. self.download(file, local);
  136. return info
  137. def download(self, file, local):
  138. if 'http' in file:
  139. import requests
  140. r = requests.get(file, stream=True)
  141. with open(local, 'wb') as up:
  142. for chunk in r.iter_content(chunk_size=1024):
  143. if chunk:
  144. up.write(chunk)
  145. else:
  146. import shutil
  147. shutil.copyfile(file, local)
  148. if File.exists(local):
  149. return True
  150. return False
  151. def command(self, info):
  152. convert = 'cd ' + info['path'] + ' && '
  153. if 'pdf' not in info['ext']:
  154. #convert = convert + 'libreoffice --invisible --convert-to pdf ' + info['local']
  155. convert = convert + 'soffice --headless --invisible --convert-to pdf ' + info['local']
  156. convert = convert + ' && '
  157. else:
  158. info['pdf'] = info['local']
  159. convert = convert + 'pdf2htmlEX --zoom 1 --hdpi 100 --vdpi 100 --use-cropbox 0 --no-drm 1 --split-pages 1 '
  160. convert = convert + '--embed-css 0 --embed-javascript 0 --embed-image 0 --embed-font 1 --process-outline 0 '
  161. convert = convert + '--embed-external-font 0 --dest-dir '+info['path']+' --page-filename %d.page ' + info['pdf']
  162. return convert
  163. def total(self, path):
  164. page = 0
  165. for parentdir,dirname,filenames in os.walk(path):
  166. for filename in filenames:
  167. if os.path.splitext(filename)[1]=='.page':
  168. page = page + 1
  169. return page
  170. def handle(self, id):
  171. model = Demeter.model('convert')
  172. model.id = id
  173. info = model.select(type='fetchone')
  174. if not info:
  175. return
  176. siteModel = Demeter.model('site')
  177. siteModel.id = info['site_id']
  178. site = siteModel.select(type='fetchone')
  179. status = True
  180. if info['status'] == 1 or info['status'] == 4:
  181. status = False
  182. if info and status == False:
  183. model.id = id
  184. update = {}
  185. update['status'] = 2
  186. model.update(update)
  187. if not File.exists(info['local']):
  188. self.download(info['file'], info['local'])
  189. if not File.exists(info['html']):
  190. #if info:
  191. File.mkdir(info['path'])
  192. if 'txt' in info['ext']:
  193. import chardet
  194. file_path = info['local']
  195. with open(file_path, 'rb') as fp:
  196. file_data = fp.read()
  197. result = chardet.detect(file_data)
  198. fp.close()
  199. if result['encoding'] != 'utf-8':
  200. file_content = file_data.decode(result['encoding'])
  201. f = open(file_path, 'w')
  202. f.write(file_content)
  203. f.close()
  204. handle = self.command(info)
  205. Shell.popen(handle)
  206. if File.exists(info['html']):
  207. # 处理图片
  208. self.pic(info)
  209. #self.string_switch(info['html'], "taste", "tasting")
  210. # 获取有多少页
  211. page = self.total(info['path'])
  212. model.id = id
  213. size = os.path.getsize(info['local'])
  214. update = {}
  215. update['file_size'] = size
  216. update['page'] = page
  217. update['status'] = 3
  218. model.update(update)
  219. # 通知接口 通知应用成功转换
  220. info['page'] = page
  221. info['file_size'] = size
  222. info['convert_status'] = 1
  223. self.api(info, site)
  224. return
  225. model.id = id
  226. update = {}
  227. update['status'] = 4
  228. model.update(update)
  229. # 通知接口 通知应用失败转换
  230. info['page'] = 0
  231. info['file_size'] = 0
  232. info['convert_status'] = 2
  233. self.api(info, site)
  234. def api(self, info, site):
  235. if 'file_id' in info and info['file_id']:
  236. api = site['api']
  237. appid = site['appid']
  238. appsecret = site['appsecret']
  239. timestamp = Demeter.time()
  240. nonce = Demeter.hash()
  241. file = info['key']
  242. file_id = info['file_id']
  243. uid = info['uid']
  244. param = self.signature(site['id'], appid, appsecret, timestamp, nonce, file, file_id, uid)
  245. param['url'] = 'main/view'
  246. param['img'] = info['url'] + '.jpg'
  247. param['page'] = info['page']
  248. param['ext'] = info['ext']
  249. param['file_size'] = info['file_size']
  250. param['status'] = info['convert_status']
  251. Demeter.curl(api, param, 'post')
  252. def pic(self, info):
  253. from pdf2jpg import pdf2jpg
  254. from wand.image import Image
  255. width = 800
  256. # 对生成的图片进行缩放
  257. files = File.getFiles(info['path'])
  258. if files:
  259. for file in files:
  260. if 'jpg' in file or 'png' in file:
  261. file = info['path'] + file
  262. with Image(filename=file) as img:
  263. target_width, target_height = self.getSize(width, img.width, img.height)
  264. img.sample(target_width, target_height)
  265. img.save(filename=file)
  266. # 生成图片
  267. dest = info['html'] + '.photo'
  268. result = pdf2jpg.convert_pdf2jpg(info['pdf'], dest, pages="0,1")
  269. i = 0
  270. for j in result[0]['output_jpgfiles']:
  271. source = j
  272. if i == 0:
  273. dest = info['html'] + '.jpg'
  274. else:
  275. dest = info['html'] + '.jpg_' + str(i) + '.jpg'
  276. command = 'mv '+source+' ' + dest
  277. Shell.popen(command)
  278. with Image(filename=dest) as img:
  279. target_width, target_height = self.getSize(width, img.width, img.height)
  280. img.sample(target_width, target_height)
  281. img.save(filename=dest)
  282. i = i+1
  283. '''
  284. from wand.image import Image
  285. pdf = Image(filename=source, resolution=50)
  286. jpg = pdf.convert('jpg')
  287. req_image = []
  288. i = 0
  289. for img in jpg.sequence:
  290. if i == 0:
  291. img_page = Image(image=img)
  292. req_image.append(img_page.make_blob('jpg'))
  293. i = i+1
  294. for img in req_image:
  295. ff = open(dest, 'wb')
  296. ff.write(img)
  297. ff.close()
  298. '''
  299. def getSize(self, target_width, img_width, img_height):
  300. if img_width > target_width:
  301. ratio = target_width / img_width
  302. target_height = int(ratio * img_height)
  303. else:
  304. target_width = img_width
  305. target_height = img_height
  306. return target_width, target_height
  307. def string_switch(self, x,y,z,s=1):
  308. with open(x, "r", encoding="utf-8") as f:
  309. #readlines以列表的形式将文件读出
  310. lines = f.readlines()
  311. with open(x, "w", encoding="utf-8") as f_w:
  312. #定义一个数字,用来记录在读取文件时在列表中的位置
  313. n = 0
  314. #默认选项,只替换第一次匹配到的行中的字符串
  315. if s == 1:
  316. for line in lines:
  317. if y in line:
  318. line = line.replace(y,z)
  319. f_w.write(line)
  320. n += 1
  321. break
  322. f_w.write(line)
  323. n += 1
  324. #将剩余的文本内容继续输出
  325. for i in range(n,len(lines)):
  326. f_w.write(lines[i])
  327. #全局匹配替换
  328. elif s == 'g':
  329. for line in lines:
  330. if y in line:
  331. line = line.replace(y,z)
  332. f_w.write(line)