Exemplo n.º 1
0
 def add_image_part(self, multi_part, filename):
     """Adds the image field to the multipart object."""
     image_part = QHttpPart()
     image_part.setHeader(QNetworkRequest.ContentTypeHeader,
                          QVariant('application/octet-stream'))
     image_part.setHeader(
         QNetworkRequest.ContentDispositionHeader,
         QVariant('form-data; name="file"'))
     f = QFile(filename)
     f.open(QIODevice.ReadOnly)
     image_part.setBodyDevice(f)
     f.setParent(multi_part)
     multi_part.append(image_part)
Exemplo n.º 2
0
 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 uploadImage(self, pathToImage):
        img = QFile(pathToImage)
        img.open(QIODevice.ReadOnly)
        imgPart = QHttpPart()
        txt = 'form-data; name="file"; filename="' + os.path.basename(
            pathToImage) + '"'
        imgPart.setHeader(QNetworkRequest.ContentDispositionHeader, txt)
        imgPart.setHeader(QNetworkRequest.ContentTypeHeader, 'image/zip')
        imgPart.setBodyDevice(img)

        multiPart = QHttpMultiPart(QHttpMultiPart.FormDataType)
        multiPart.append(imgPart)

        url = self.baseurl + 'projectimage/upload.action?'

        response = self.http.request(url, method='POST', body=multiPart)
        if response[0]['status'] > 199 and response[0]['status'] < 210:
            # if icon upload was successfull, server returns id of the new icon
            # in it's database
            id = json.loads(response[1])['data']['id']
            return id
        else:
            return False
Exemplo n.º 4
0
 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
Exemplo n.º 5
0
    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
    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']