def _render2(self): IPersistentLogger(self.context).log('convert') payload = decode_json_payload(self.request) if 'mapping' not in payload: raise ValueError('No "mapping" found in JSON payload') rules = payload['mapping'] conversion_id = payload.get('converter', 'docx2ditatopic') conversion_endpoint_url = ENDPOINTS[conversion_id]['url'] rewriter = RuleRewriter(rules) handle = self.context.webdav_handle() zip_tmp = temp_zip(suffix='.zip') with fs.zipfs.ZipFS(zip_tmp, 'w') as zip_fp: for name in handle.walkfiles(): if name.endswith('.sha256'): continue name_in_zip = rewriter.rewrite(name) if name_in_zip: with handle.open(name, 'rb') as fp_in, \ zip_fp.open(name_in_zip, 'wb') as fp: fp.write(fp_in.read()) with delete_after(zip_tmp): zip_out = convert_crex(zip_tmp, crex_url=conversion_endpoint_url) store_zip(self.context, zip_out, 'current') conversion_info = self.get_crex_info() conversion_info['status'] = CREX_STATUS_SUCCESS self.set_crex_info(conversion_info) with delete_after(zip_out): self.request.response.setHeader( 'content-length', str(os.path.getsize(zip_out))) self.request.response.setHeader('content-type', 'application/zip') self.request.response.setHeader( 'content-disposition', 'attachment; filename={}.zip'.format(self.context.getId())) return filestream_iterator(zip_out)
def convert_crex(zip_path, crex_url=None, crex_username=None, crex_password=None): """ Send ZIP archive with content to be converted to C-Rex. Returns name of ZIP file with converted resources. """ ts = time.time() registry = getUtility(IRegistry) settings = registry.forInterface(ICRexSettings) crex_conversion_url = crex_url or settings.crex_conversion_url crex_conversion_username = crex_username or settings.crex_conversion_username crex_conversion_password = crex_password or settings.crex_conversion_password crex_token = settings.crex_conversion_token # Fetch authentication token if necessary (older than one hour) crex_token_last_fetched = settings.crex_conversion_token_last_fetched or datetime.datetime( 2000, 1, 1) diff = datetime.datetime.utcnow() - crex_token_last_fetched if not crex_token or diff.total_seconds() > 3600: f = furl.furl(crex_conversion_url) token_url = '{}://{}/api/Token'.format( f.scheme, f.host, crex_conversion_url) headers = {'content-type': 'application/x-www-form-urlencoded'} params = dict( username=crex_conversion_username, password=crex_conversion_password, grant_type='password') result = requests.post(token_url, data=params, headers=headers) if result.status_code != 200: msg = u'Error retrieving DOCX conversion token from webservice (HTTP code {}, Message {})'.format( result.status_code, result.text) LOG.error(msg) raise CRexConversionError(msg) data = result.json() crex_token = data['access_token'] settings.crex_conversion_token = crex_token settings.crex_conversion_token_last_fetched = datetime.datetime.utcnow() LOG.info('Fetching new DOCX authentication token - successful') else: LOG.info('Fetching DOCX authentication token from Plone cache') headers = {'authorization': 'Bearer {}'.format(crex_token)} with open(zip_path, 'rb') as fp: try: LOG.info(u'Starting C-Rex conversion of {}, size {} '.format(zip_path, os.path.getsize(zip_path))) result = requests.post( crex_conversion_url, files=dict(source=fp), headers=headers) except requests.ConnectionError: msg = u'Connection to C-REX webservice failed' raise CRexConversionError(msg) if result.status_code == 200: msg = u'Conversion successful (HTTP code {}, duration: {:2.1f} seconds))'.format( result.status_code, time.time() - ts) LOG.info(msg) zip_out = temp_zip(suffix='.zip') with open(zip_out, 'wb') as fp: fp.write(result.content) return zip_out else: # Forbidden -> invalid token -> invalidate token stored in Plone if result.status_code == 401: settings.crex_conversion_token = u'' settings.crex_conversion_token_last_fetched = datetime.datetime( 1999, 1, 1) msg = u'Conversion failed (HTTP code {}, message {})'.format( result.status_code, result.text) LOG.error(msg) raise CRexConversionError(msg)