def add_text_parts(self, multi_part, fields): """Adds all text fields to the multipart object.""" for key in fields: text_part = QHttpPart() text_part.setHeader(QNetworkRequest.ContentDispositionHeader, QVariant('form-data; name="{0}"'.format(key))) text_part.setBody(self.str_to_byte_array(fields[key])) multi_part.append(text_part)
def delegate_download(self, action_url, method, headers, data, js_cb_func, js_cb_object_id): """ :param action_url: url to call on ipt api :param method: string like 'POST' :param headers: list of strings :param data: list of dictionaries {name (string) value(string)} :param delegate_download_js_cb: javascript callback :param js_cb_object_id: id of the javascript object to be called back """ # TODO: Accept also methods other than POST if method != 'POST': self.call_js_cb(js_cb_func, js_cb_object_id, None, 1, 'Method %s not allowed' % method) return False if ':' in action_url: qurl = QUrl(action_url) elif action_url.startswith('/'): qurl = QUrl("%s%s" % (self.parent().host, action_url)) else: url = "%s/%s" % ('/'.join([ str(x) for x in self.parent().web_view.url().toEncoded().split( '/')[:-1] ]), action_url) qurl = QUrl(url) manager = self.parent().web_view.page().networkAccessManager() request = QNetworkRequest(qurl) request.setAttribute(REQUEST_ATTRS['instance_finished_cb'], self.manager_finished_cb) request.setAttribute(REQUEST_ATTRS['js_cb_object_id'], js_cb_object_id) request.setAttribute(REQUEST_ATTRS['js_cb_func'], js_cb_func) for header in headers: request.setRawHeader(header['name'], header['value']) multipart = QHttpMultiPart(QHttpMultiPart.FormDataType) for d in data: part = QHttpPart() part.setHeader(QNetworkRequest.ContentDispositionHeader, "form-data; name=\"%s\"" % d['name']) part.setBody(d['value']) multipart.append(part) reply = manager.post(request, multipart) # NOTE: needed to avoid segfault! multipart.setParent(reply) # delete the multiPart with the reply return True
def uploadLayer(self, pathToZipFile, dataType): url = self.baseurl + '/import/create-layer.action' # the following creates a QHttpMultiPart with 2 parts, one defining the # dataType (i.e. Vector or Raster) and one with the binary file data itself textpart = QHttpPart() textpart.setHeader(QNetworkRequest.ContentDispositionHeader, 'form-data; name="dataType"') if PYTHON_VERSION >= 3: textpart.setBody(dataType.encode('utf-8')) else: textpart.setBody(dataType) file = QFile(pathToZipFile) file.open(QIODevice.ReadOnly) lyr = 'form-data; name="file"; filename="' + os.path.basename( pathToZipFile) + '"' layerpart = QHttpPart() layerpart.setHeader(QNetworkRequest.ContentTypeHeader, 'application/zip') layerpart.setHeader(QNetworkRequest.ContentDispositionHeader, lyr) layerpart.setBodyDevice(file) multipart = QHttpMultiPart(QHttpMultiPart.FormDataType) multipart.append(textpart) multipart.append(layerpart) response = self.http.request(url, method='POST', body=multipart) res = json.loads(response[1]) if res['success']: self.userInfo(response[0]['status'], 'New Vector Layer', 'uploaded') else: if res['error'] == 'NO_CRS': self.requestCrsUpdateOnLayer(res['importJobId']) else: self.userInfo(response[0]['status'], 'New Vector Layer', 'uploaded') return response[0]['status']
def upload_files(self, layer, field_index, features): """ Upload given features' source files to remote server and return a dict formatted as changeAttributeValues expects to update 'datos' attribute to a remote location. """ if not QSettings().value( 'Asistente-LADM_COL/sources/document_repository', False, bool): self.message_with_duration_emitted.emit( QCoreApplication.translate( "SourceHandler", "The source files were not uploaded to the document repository because you have that option unchecked. You can still upload the source files later using the 'Upload Pending Source Files' menu." ), Qgis.Info, 10) return dict() # Test if we have Internet connection and a valid service dlg = self.qgis_utils.get_settings_dialog() res, msg = dlg.is_source_service_valid() if not res: msg['text'] = QCoreApplication.translate( "SourceHandler", "No file could be uploaded to the document repository. You can do it later from the 'Upload Pending Source Files' menu. Reason: {}" ).format(msg['text']) self.message_with_duration_emitted.emit( msg['text'], Qgis.Info, 20) # The data is still saved, so always show Info msg return dict() file_features = [ feature for feature in features if not feature[field_index] == NULL and os.path.isfile(feature[field_index]) ] total = len(features) not_found = total - len(file_features) upload_dialog = UploadProgressDialog(len(file_features), not_found) upload_dialog.show() count = 0 upload_errors = 0 new_values = dict() for feature in file_features: data_url = feature[field_index] file_name = os.path.basename(data_url) nam = QNetworkAccessManager() #reply.downloadProgress.connect(upload_dialog.update_current_progress) multiPart = QHttpMultiPart(QHttpMultiPart.FormDataType) textPart = QHttpPart() textPart.setHeader(QNetworkRequest.ContentDispositionHeader, QVariant("form-data; name=\"driver\"")) textPart.setBody(QByteArray().append('Local')) filePart = QHttpPart() filePart.setHeader( QNetworkRequest.ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"{}\"".format( file_name))) file = QFile(data_url) file.open(QIODevice.ReadOnly) filePart.setBodyDevice(file) file.setParent( multiPart ) # we cannot delete the file now, so delete it with the multiPart multiPart.append(filePart) multiPart.append(textPart) service_url = '/'.join([ QSettings().value( 'Asistente-LADM_COL/sources/service_endpoint', DEFAULT_ENDPOINT_SOURCE_SERVICE), SOURCE_SERVICE_UPLOAD_SUFFIX ]) request = QNetworkRequest(QUrl(service_url)) reply = nam.post(request, multiPart) #reply.uploadProgress.connect(upload_dialog.update_current_progress) reply.error.connect(self.error_returned) multiPart.setParent(reply) # We'll block execution until we get response from the server loop = QEventLoop() reply.finished.connect(loop.quit) loop.exec_() response = reply.readAll() data = QTextStream(response, QIODevice.ReadOnly) content = data.readAll() if content is None: self.log.logMessage( "There was an error uploading file '{}'".format(data_url), PLUGIN_NAME, Qgis.Critical) upload_errors += 1 continue try: response = json.loads(content) except json.decoder.JSONDecodeError: self.log.logMessage( "Couldn't parse JSON response from server for file '{}'!!!" .format(data_url), PLUGIN_NAME, Qgis.Critical) upload_errors += 1 continue if 'error' in response: self.log.logMessage( "STATUS: {}. ERROR: {} MESSAGE: {} FILE: {}".format( response['status'], response['error'], response['message'], data_url), PLUGIN_NAME, Qgis.Critical) upload_errors += 1 continue reply.deleteLater() if 'url' not in response: self.log.logMessage( "'url' attribute not found in JSON response for file '{}'!" .format(data_url), PLUGIN_NAME, Qgis.Critical) upload_errors += 1 continue url = self.get_file_url(response['url']) new_values[feature.id()] = {field_index: url} count += 1 upload_dialog.update_total_progress(count) if not_found > 0: self.message_with_duration_emitted.emit( QCoreApplication.translate( "SourceHandler", "{} out of {} records {} not uploaded to the document repository because {} file path is NULL or it couldn't be found in the local disk!" ).format( not_found, total, QCoreApplication.translate("SourceHandler", "was") if not_found == 1 else QCoreApplication.translate( "SourceHandler", "were"), QCoreApplication.translate("SourceHandler", "its") if not_found == 1 else QCoreApplication.translate( "SourceHandler", "their")), Qgis.Info, 0) if len(new_values): self.message_with_duration_emitted.emit( QCoreApplication.translate( "SourceHandler", "{} out of {} files {} uploaded to the document repository and {} remote location stored in the database!" ).format( len(new_values), total, QCoreApplication.translate("SourceHandler", "was") if len(new_values) == 1 else QCoreApplication.translate( "SourceHandler", "were"), QCoreApplication.translate("SourceHandler", "its") if len(new_values) == 1 else QCoreApplication.translate( "SourceHandler", "their")), Qgis.Info, 0) if upload_errors: self.message_with_duration_emitted.emit( QCoreApplication.translate( "SourceHandler", "{} out of {} files could not be uploaded to the document repository because of upload errors! See log for details." ).format(upload_errors, total), Qgis.Info, 0) return new_values