Двоичный файл POST для тикета ServiceNow REST API - удаление границ и Content-Type - PullRequest
2 голосов
/ 14 июля 2020

Я пытаюсь прикрепить двоичный файл (Excel, MS-Word, Image или что-то еще) к билету ServiceNow, используя метод POST, доступный в их REST API.

Он отлично работает, когда я пытаюсь это сделать с помощью приложения Postman, однако, когда я пытаюсь сделать это с помощью кода C#, файл добавляется успешно, однако в начале и конце файла есть некоторые данные, из-за которых файлы больше не действительны. Если я открою прикрепленные файлы с помощью Notepad ++, я вижу, что файл имеет что-то вроде ниже:

--dc5fc6f1-c907-4a26-b410-1d54256954d6
Content-Disposition: form-data; name=Attachment; filename=Download_14Jul20151332195868.xlsx; filename*=utf-8''Download_14Jul20151332195868.xlsx

Если я удалю указанные выше строки из файла и сохраню их снова, тогда я смогу открыть файл в excel. То же самое происходит с любым другим типом файла.

Я использую ниже URL-адрес для POST файла в ServiceNow: https://mycompany.service-now.com/api/now/attachment/file?table_name=incident&table_sys_id=1abc60ccdabc1c14215fc082ba9619b0&file_name=SampleExcel3.xlsx

И ниже мой код:

        private static string SendMultiPartRequest(string URL, ExecutionEnvironment executionEnvironment)
        {
            var response = "";
            try
            {
                byte[] file_bytes = File.ReadAllBytes(AttachmentFilePath);
                if (!string.IsNullOrWhiteSpace(AttachmentFilePath))
                {
                    using (var client = CreateNewClient(URL, executionEnvironment))
                    {
                        using (var multipartContent = new MultipartFormDataContent())
                        {
                            multipartContent.Add(new StreamContent(new MemoryStream(file_bytes)), "Attachment", AttachmentFilePath.Substring(AttachmentFilePath.LastIndexOf("\\") + 1));
                            //multipartContent.Headers.Remove("Content-Type");

                            Task responseTask = client.PostAsync(WSIUrl, multipartContent).ContinueWith((Task<HttpResponseMessage> authRes) =>
                            {
                                response = HandleResponse(authRes);
                            });

                            responseTask.Wait();
                        }
                    }
                }
                else
                {
                    response = "{ \"ErrorMessage\" : \"Attachment file not specified.\"}";
                }
            }
            catch (Exception ex)
            {
                response = "{ \"ErrorMessage\" : \"Unspecified error: " + ex.Message + " \"}";
            }
            return response;
        }

Я также попытался удалить заголовок, но мне не удалось прикрепить файл, когда я не комментировал эту строку:

  //multipartContent.Headers.Remove("Content-Type");

Я не могу контролировать, как ServiceNow API использует файл отправлен. Пожалуйста, предложите, как я могу отправить двоичный файл для прикрепления к заявке ServiceNow.

ОБНОВЛЕНИЕ: Я все еще пытаюсь использовать различные параметры, но мне все равно не повезло. Я попытался изучить, как Postman может успешно прикрепить файл, и нашел ниже код из приложения Postman. Однако я не вижу в этом коде, как Postman добавляет двоичное содержимое в полезную нагрузку:

var client = new RestClient("https://mycompany.service-now.com/api/now/attachment/file?table_name=incident&table_sys_id=1abc60ccdabc1c14215fc082ba9619b0&file_name=Sample.xlsx");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "34584fo4-f91a-414f-8fd0-ff44b0c6b345");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Authorization", "Basic c4Ajc2NvcmNoOmVOdBEzOSNSQGspqr==");
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
IRestResponse response = client.Execute(request);

Однако, когда я отправляю запрос POST через приложение Postman, он работает нормально: URL-адрес, используемый в почтальон: POST - https://MyCompany.service-now.com/api/now/attachment/file?table_name=incident&table_sys_id=1abc60ccdabc1c14215fc082ba9619b0&file_name=Sample.xlsx

введите описание изображения здесь

1 Ответ

1 голос
/ 04 августа 2020

Наконец-то я получил эту работу с помощью RestSharp. Ниже приведен код, если кто-то еще ищет решение:

private static string SendMultiPartRestClient(string URL, ExecutionEnvironment executionEnvironment)
{
    string response;
    try
    {
        if (!string.IsNullOrWhiteSpace(AttachmentFilePath))
        {
            string FileNameWithoutExtension = Path.GetFileNameWithoutExtension(AttachmentFilePath);
            string FileExtension = Path.GetExtension(AttachmentFilePath);
            string AttachmentFileName = $"{FileNameWithoutExtension}{FileExtension}";

            string AskNowPasswordToBeUsed;
            if (executionEnvironment == ExecutionEnvironment.NonProduction)
                AskNowPasswordToBeUsed = AskNowPasswordEagle;
            else
                AskNowPasswordToBeUsed = AskNowPasswordProduction;

            byte[] byteArray = Encoding.ASCII.GetBytes(AskNowUserName + ":" + AskNowPasswordToBeUsed);
            var Auth = Convert.ToBase64String(byteArray);

            ServicePointManager.Expect100Continue = true;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
            
            X509Certificate2 c1 = new X509Certificate2(asknowCertPath, CertPass);

            var client = new RestClient(WSIUrl);
            client.Timeout = -1;
            client.AddDefaultHeader(DP_EXTERNAL_URL, URL);
            client.ClientCertificates = new X509CertificateCollection() { c1 };

            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", $"Basic {Auth}");
            request.AddHeader("Accept", "*/*");
            request.AddHeader("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            request.AddParameter("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                File.ReadAllBytes(AttachmentFilePath),
                ParameterType.RequestBody);

            IRestResponse restResponse = client.Execute(request);

            switch (restResponse.ResponseStatus)
            {
                case ResponseStatus.None:
                    response = "{ \"ErrorMessage\" : \"No response\"}";
                    break;
                case ResponseStatus.Completed:
                    response = restResponse.Content;
                    break;
                case ResponseStatus.Error:
                    response = "{ \"ErrorMessage\" : \"Unspecified error: " + restResponse.ErrorMessage + " \"}";
                    break;
                case ResponseStatus.TimedOut:
                    response = "{ \"ErrorMessage\" : \"Request timed out\"}";
                    break;
                case ResponseStatus.Aborted:
                    response = "{ \"ErrorMessage\" : \"Request aborted\"}";
                    break;
                default:
                    response = "{ \"ErrorMessage\" : \"Unspecified response type.\"}";
                    break;
            }
        }
        else
        {
            response = "{ \"ErrorMessage\" : \"Attachment file not specified.\"}";
        }
    }
    catch (Exception ex)
    {
        response = "{ \"ErrorMessage\" : \"Unspecified error: " + ex.Message + " \"}";
    }
    return response;
}
...