Мне нужно загрузить приложение в тест в ALM 11 HP. Для этого я создал пользовательскую функцию PHP, основанную на cURL, чтобы использовать REST API для ALM. Это код:
public function attachment($project, $domain, $entity, $id, $filename) { $qc = $this->qc_cookie; $ckfile = $this->ckfile; $eol = "\n\n"; $mime_boundary=md5(time()); $file_to_upload = '--'.$mime_boundary. $eol; $file_to_upload .= 'Content-Disposition: form-data; name="filename"'; $file_to_upload .= $eol; $file_to_upload .= $filename; $file_to_upload .= $eol; $file_to_upload .= $eol; $file_to_upload .= '--'.$mime_boundary. $eol; $file_to_upload .= 'Content-Disposition: form-data; name="description"'; $file_to_upload .= $eol; $file_to_upload .= 'Test'; $file_to_upload .= $eol; $file_to_upload .= $eol; $file_to_upload .= '--'.$mime_boundary. $eol; $file_to_upload .= 'Content-Disposition: form-data; name="file"; filename="'.$filename.'"'; $file_to_upload .= $eol; $file_to_upload .= 'Content-Type: text/plain'; $file_to_upload .= $eol; $file_to_upload .= 'Content-Transfer-Encoding: base64' . $eol . $eol; $handle = fopen($filename, 'r'); $file_to_upload .= fread($handle,filesize($filename)); $file_to_upload .= $eol; $file_to_upload .= '--'.$mime_boundary.'--'. $eol.$eol; fclose($handle); $header = array("POST /qcbin/rest/domains/".$domain."/projects/".$project."/".$entity.'/'.$id.'/attachments'." HTTP/1.1", 'Content-Type: multipart/form-data; boundary='.$mime_boundary, //'Content-Length: '.strlen($file_to_upload) ); curl_setopt($qc, CURLOPT_HTTPHEADER, $header); curl_setopt($qc, CURLOPT_POSTFIELDS, $file_to_upload); curl_setopt($qc, CURLOPT_COOKIEFILE, $ckfile); curl_setopt($qc, CURLOPT_RETURNTRANSFER, true); curl_setopt($qc, CURLOPT_URL, $this->url."/qcbin/rest/domains/".$this->domain."/projects/".$this->project."/".$entity."/".$id.'/attachments'); return curl_exec($qc); }
Когда я отправляю запрос указанному URL-адресу, я получаю следующую ошибку от ALM:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <QCRestException> <Id>qccore.general-error</Id> <Title>Illegal multi-part arguments. Attachment wasn't created.</Title> <StackTrace>java.lang.IllegalArgumentException: Illegal multi-part arguments. Attachment wasn't created.
at org.hp.qc.web.restapi.attachments.AttachmentsResource.createAttachmentMutliPart(AttachmentsResource.java:141)
at sun.reflect.GeneratedMethodAccessor985.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
...
Я хотел бы знать, что я делаю неправильно. Я следую указанной структуре полей POST, которые находятся в ссылке API. Спасибо.
Я просто решил эту проблему и очень доволен. Моя проблема заключалась в том, что я определял границу в заголовке с тире, точно так же, как они упоминаются в теле. Это было неправильно.
Вот пример (основанный на документах REST API), который работал на меня:
Заголовки:
Content-Type: multipart/form-data; boundary=myboundary
Тело:
--myboundary Content-Disposition: form-data; name="filename" anna.txt --myboundary Content-Disposition: form-data; name="file"; filename="anna.txt" banana --myboundary--
Я все еще не могу загружать двоичные вложения, но для меня это большое улучшение.
Изменить – для загрузки любого типа файла для меня работал следующий код powershell:
$contents = gc "my file path" $body = @" --boundary Content-Disposition: form-data; name="filename" $name --boundary Content-Disposition: form-data; name="file"; filename="$name" $contents --boundary-- "@ $headers = @{"Content-Length" = $body.Length; "Content-Type" = "multipart/form-data; boundary=$boundary"} Invoke-RestMethod -Uri "ALM attachment URI" -Method Post -ContentType "multipart/form-data;boundary=boundary" -WebSession $global:session -Body $body
Изменить: вот мое последнее обновление – функция python, которая успешно загружает вложение через REST API. Обратите внимание, что это часть большой библиотеки, но, надеюсь, вы получите идею:
def upload_attachment(self, entity_type, id, file_name): """ Name upload_attachment Description Uploads an attachment to the supplied entity Parameters entity_type: the entity type - ie 'test-instance', 'run', etc. id: the integer id of the entity file_name: the name of the file in the local filesystem Returns """ print 'Uploading attachment to %s id=%s' % (entity_type, id) with open(file_name, 'rb') as file: bin_data = file.read() qurl = '%s/qcbin/rest/domains/%s/projects/%s/%s/%s/attachments' % \ (self.url, self.domain, self.project, entity_type, id) headers = {'Content-Type' : 'multipart/form-data; boundary=uploadboundary'} body = """--uploadboundary Content-Disposition: form-data; name="filename" %s --uploadboundary Content-Disposition: form-data; name="file"; filename="%s" %s --uploadboundary--""" % (file_name, file_name, bin_data) rsp = self.session.post(qurl, data=body, headers=headers) if rsp.status_code != 201: raise Exception('Failed to upload %s - code=%s message=%s' % \ (file_name, rsp.status_code, rsp.text))
Надеюсь, кто-то найдет это полезным.
Изменить: код не работал, поскольку он является частью большей библиотеки. Ниже приведен пример публикации простого текстового файла с именем «hello.txt» с содержимым «Hello !!» Он был создан с кодом сверху:
Заголовки:
'Content-Type': 'multipart/form-data; boundary=uploadboundary'
Тело:
--uploadboundary Content-Disposition: form-data; name="filename" hello.txt --uploadboundary Content-Disposition: form-data; name="file"; filename="hello.txt" Hello!! --uploadboundary--