來自 SOAP 和 REST 客戶端共享的 SOAP 響應的 HTTP Cookie 標頭

Acumatica 的基於 SOAP 契約的 API 存在限制,允許僅為頂級實體下載附件。遺憾的是,任何嘗試使用 GetFiles() 方法獲取詳細資訊實體的附件都會導致錯誤沒有螢幕繫結的實體不能用作頂級實體。告訴我們它只能用於頂層實體。 Web 服務端點中定義的級別實體。

GetFiles() 方法的另一個限制是它始終返回附加到實體的所有檔案的內容。沒有選項可以先檢索檔名,然後決定從 Acumatica 下載哪些特定檔案。

值得慶幸的是,有一種更好,更可控的方式來處理隨基於合同的 REST API 提供的附件。作為基於合同的 REST API 匯出的每個實體的一部分返回的 files 陣列僅包含:

  • 檔名( 檔名屬性)
  • 檔案識別符號( id 屬性)
  • 超文字引用( href 屬性),可以在以後用於下載檔案內容

有關從 Web 服務端點獲取附加到任何實體的檔案列表並通過基於合同的 REST API 檢索特定檔案內容的示例,請檢視 Acumatica 產品幫助

如果整個整合專案是使用基於 SOAP 契約的 API 開發的,那麼如何下載附加到詳細實體的檔案?如下面的程式碼片段所示,可以將 SOAP 響應從 SOAP 響應傳遞到專門用於處理附件的 REST API 客戶端:

using (var soapClient = new DefaultSoapClient())
{
    var address = new Uri("http://localhost/AcumaticaERP/entity/Default/6.00.001/");
    CookieContainer cookieContainer;
    using (new OperationContextScope(soapClient.InnerChannel))
    {
        soapClient.Login(login, password, null, null, null);
        string sharedCookie = WebOperationContext.Current.IncomingResponse.Headers["Set-Cookie"];
        cookieContainer = new CookieContainer();
        cookieContainer.SetCookies(address, sharedCookie);
    }
    try
    {
        var shipment = new Shipment()
        {
            ShipmentNbr = new StringSearch { Value = "001301" },
            ReturnBehavior = ReturnBehavior.OnlySpecified
        };
        shipment = soapClient.Get(shipment) as Shipment;

        var restClient = new HttpClient(
            new HttpClientHandler
            {
                UseCookies = true,
                CookieContainer = cookieContainer
            });
        restClient.BaseAddress = address;// new Uri("http://localhost/059678/entity/Default/6.00.001/");

        var res = restClient.GetAsync("Shipment/" + shipment.ID + "?$expand=Packages")
            .Result.EnsureSuccessStatusCode();
        var shipmentWithPackages = res.Content.ReadAsStringAsync().Result;

        JObject jShipment = JObject.Parse(shipmentWithPackages);
        JArray jPackages = jShipment.Value<JArray>("Packages");
        foreach (var jPackage in jPackages)
        {
            JArray jFiles = jPackage.Value<JArray>("files");
            string outputDirectory = ".\\Output\\";
            if (!Directory.Exists(outputDirectory))
            {
                Directory.CreateDirectory(outputDirectory);
            }

            foreach (var jFile in jFiles)
            {
                string fullFileName = jFile.Value<string>("filename");
                string fileName = Path.GetFileName(fullFileName);
                string href = jFile.Value<string>("href");

                res = restClient.GetAsync(href).Result.EnsureSuccessStatusCode();
                byte[] file = res.Content.ReadAsByteArrayAsync().Result;
                System.IO.File.WriteAllBytes(outputDirectory + fileName, file);
            }
        }
    }
    finally
    {
        soapClient.Logout();
    }
}