0

我正在使用 Delphi XE5,我正在尝试使用 Bulk API Upload 将商品发送到沃尔玛,但我正在努力与沃尔玛的服务器建立正确的连接。我已经在这里检查了一些类似的问题,例如Walmart API - payload mime type issue

最奇怪的是,该提要实际上已被沃尔玛接受(我在提要列表中看到它)但我收到内部服务器错误,然后收到无意义的字符(可能是编码类型或只是一种错误),例如

(#$D#$A#$1F#$008B#8#0#0#0#0#0#0#3#$D'A±'#$D#$0080'0'#$C#4'AU~'# 2'v ?d'#$0087#4'?'#1#$0091'OE'#$E#$008A'O'#$1E'®?O?'#$18#$0091#$A#$0091'M^'# $C'?;'#$1D'G'#$A'dR±U?oip?m'#$1A'AVS'#4#$16'R?iR'#$1B#$0095'RO?}u'# 0'enIjM'#0#0#0)

因此,我使用 Indy IdHTTP,并且尝试使用TIdMultipartFormDataStream并在接收内部服务器错误的情况下自行创建有效负载。我想我以某种方式破坏了他们的解析器,因为如果我在一开始就错过了一个 CR LF (#13#10),我会得到一个特定的错误

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:errors xmlns:ns2="http://walmart.com/"><ns2:error><ns2:code>SYSTEM_ERROR.GMP_GATEWAY_API</ns2:code><ns2:field>PDR-0012</ns2:field><ns2:description></ns2:description><ns2:info>System encountered some internal error.</ns2:info><ns2:severity>ERROR</ns2:severity><ns2:category>SYSTEM</ns2:category><ns2:causes/><ns2:errorIdentifiers/></ns2:error></ns2:errors>

如果我在最后添加一个额外的 CRLF,则会收到另一个错误,指出请求中有多个提要。所以我真的认为有什么东西使服务器/解析器返回内部错误,但我没有得到什么,我再次重复提要实际上被接受,然后在我收到此错误的情况下由服务器处理。

这是一个示例请求,其中包含我自己创建的有效负载:

标头

POST /v3/feeds?feedType=item HTTP/1.1
Content-Type: multipart/form-data; boundary=qwerty
Content-Length: 5077
WM_SVC.NAME: Walmart Marketplace
WM_QOS.CORRELATION_ID: {67F0E2F9-5EAC-4E8C-9C90-650D8F7B3B7A}
WM_SEC.TIMESTAMP: 1528364885909
WM_SEC.AUTH_SIGNATURE: nSHgqzPOtzSR4wJU+U/vQJk+rk6Ke2QwodTHjzkjau2BonXZxiU9e+3NFPzaat2OUyc+vr0jqRk0H0QWTSC21PrI87mvqei5UJCJwNiIx0zVjAGpxsnIuvtIKkQsBpuUAa8C6SjTiTpDRsNt4IOxrk+tLWxlwQubWVCV+009a6o=
WM_CONSUMER.ID: 16248274-1f53-4e6d-880e-b5417698b878
WM_CONSUMER.CHANNEL.TYPE: 0f3e4dd4-0514-4346-b39d-af0e00ea066d
Host: marketplace.walmartapis.com
Accept: application/xml, */*
Accept-Encoding: identity
Accept-Language: en-US
User-Agent: Mozilla/3.0 (compatible; Indy Library)

要求

--qwerty

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<MPItemFeed xmlns:ns2="http://walmart.com/">
    <MPItemFeedHeader>
        <version>3.1</version>
        <requestId>{694A5564-7E8E-46C7-B772-C944A8C9CF99}</requestId>
        <mart>WALMART_US</mart>
    </MPItemFeedHeader>
    <MPItem>
        <processMode>REPLACE_ALL</processMode>
        <sku>w-cc-a1-4pk-white-l</sku>
        <productIdentifiers>
            <productIdentifier>
                <productIdType>UPC</productIdType>
                <productId>192082276845</productId>
            </productIdentifier>
        </productIdentifiers>
        <MPProduct>
            <SkuUpdate>Yes</SkuUpdate>
            <productName>Caramel Cantina 4 Pack Sleeping Nursing Cross Front Maternity Bra (Large, White)</productName>
            <ProductIdUpdate>Yes</ProductIdUpdate>
            <category>
                <ClothingCategory>
                    <Clothing>
                        <shortDescription>Stretchy comfort cross front sleep bra by Caramel Cantina. Whether for nursing / maternity or for wearing as a sleep bra (or both nursing and sleep bras) - you&apos;ll experience a wire free regular back strap sleep bra. This mid-weight fabric but light support wireless bra is great for all day wear and comfort.  The straps are wider than a standard bra - offering a longer range of wear time.   Great for wearing indoors (ie when you&apos;re kicking around the home or going to bed). These are padless - most moms use their own favorite nursing pads with these (though no pads are included). The front cups have two layers of fabric to add a bit more support (though we still call them our light support comfort bra). The criss cross front style allows for easy access while nursing your baby. 92% Nylon 8% Spandex fabric washes up nicely.  Cool wash and cool dry. Hang dry for longer life. The straps narrowest point at the shoulders are 1.25-1.5 inches (depending on the size). The bras are super stretchy - if you&apos;re looking for something super supportive (ie - they pull you in really tight - more like a sports bra) these probably aren&apos;t what you&apos;re looking for.  Not recommended for heavy sports activity. Best worn for activities such as walking, sleeping, lounging, light activity, running errands, etc.</shortDescription>
                        <keyFeatures>
                            <keyFeaturesValue>4 Pack Includes 4 Bras of the Same Design - Color Option Above</keyFeaturesValue>
                            <keyFeaturesValue>Soft Cup - Front Double Layered - No padding - Wireless</keyFeaturesValue>
                            <keyFeaturesValue>Super Soft Sleep In Style Bra - Great for Nursing or Sleeping</keyFeaturesValue>
                            <keyFeaturesValue>Criss Cross Front Design Gives Easy Nursing Access</keyFeaturesValue>
                            <keyFeaturesValue>Regular Straps - Scoop Back Design - Strap Width 1.25-1.5 Inches Depending on Size</keyFeaturesValue>
                        </keyFeatures>
                        <brand>Caramel Cantina</brand>
                        <mainImageUrl>https://www.dancecheerskate.com/_inv/D54173DB8F934DB2A4C68D24FAC087F5/wm-cc-a1-4pk-white.jpg</mainImageUrl>
                        <productSecondaryImageURL>
                            <productSecondaryImageURLValue>https://www.dancecheerskate.com/_inv/D54173DB8F934DB2A4C68D24FAC087F5/wm-cc-a1-wht-m1.jpg</productSecondaryImageURLValue>
                        </productSecondaryImageURL>
                        <color>White</color>
                        <clothingSize>Large</clothingSize>
                        <variantGroupId>cc-a1-4pk-parent</variantGroupId>
                        <variantAttributeNames>
                            <variantAttributeName>color</variantAttributeName>
                            <variantAttributeName>clothingSize</variantAttributeName>
                        </variantAttributeNames>
                        <countryOfOriginTextiles>Imported</countryOfOriginTextiles>
                        <fabricCareInstructions>
                            <fabricCareInstruction>Machine wash cold gentle cycle with like colors. Hang Dry. Do Not Bleach. Do Not Iron.</fabricCareInstruction>
                        </fabricCareInstructions>
                        <multipackQuantity>1</multipackQuantity>
                        <countPerPack>4</countPerPack>
                        <count>4</count>
                        <pattern>Solid</pattern>
                        <material>Nylon; Spandex</material>
                        <gender>Female</gender>
                        <ageGroup>
                            <ageGroupValue>Adult</ageGroupValue>
                        </ageGroup>
                        <clothingSizeGroup>Maternity</clothingSizeGroup>
                        <isSet>No</isSet>
                        <requiresTextileActLabeling>Yes</requiresTextileActLabeling>
                        <clothingTopStyle>Sleep Bra</clothingTopStyle>
                        <upperBodyStrapConfiguration>Regular</upperBodyStrapConfiguration>
                        <braStyle>Nursing</braStyle>
                        <clothingStyle>Maternity</clothingStyle>
                        <clothingFit>Maternity</clothingFit>
                        <isMaternity>Yes</isMaternity>
                        <swatchImages>
                            <swatchImage>
                                <swatchVariantAttribute>color</swatchVariantAttribute>
                                <swatchImageUrl>https://www.dancecheerskate.com/_inv/D54173DB8F934DB2A4C68D24FAC087F5/wm-cc-a1-4pk-white.jpg</swatchImageUrl>
                            </swatchImage>
                        </swatchImages>
                    </Clothing>
                </ClothingCategory>
            </category>
        </MPProduct>
        <MPOffer>
            <price>25.00</price>
            <ShippingWeight>
                <measure>11.80</measure>
                <unit>lb</unit>
            </ShippingWeight>
            <ProductTaxCode>2038895</ProductTaxCode>
        </MPOffer>
    </MPItem>
</MPItemFeed>
--qwerty--

我得到的回应如下

HTTP/1.1 500 Internal Server Error
Method: null
URI: null
WM_CONSUMER.ID: 16248274-1f53-4e6d-880e-b5417698b878
WM_CONSUMER.INTIMESTAMP: 
WM_QOS.CORRELATION_ID: {67F0E2F9-5EAC-4E8C-9C90-650D8F7B3B7A}
WM_SEC.AUTH_TOKEN: 
WM_SEC.REFRESH_AUTH_TOKEN: 
WM_SVC.CLASS_NAME: com.walmart.services.impl.GMPGatewayService$$EnhancerBySpringCGLIB$$c88958a9
WM_SVC.ENV: prod
WM_SVC.INTIMESTAMP: 1528364905439
WM_SVC.METHOD_NAME: doPostMultiPart
WM_SVC.NAME: Walmart Marketplace
WM_SVC.OUTTIMESTAMP: 1528364905567
WM_SVC.SERVER_IP: 10.65.34.219
WM_SVC.SERVER_NAME: PartnerGMPService-5480119-4-96141283
WM_SVC.VERSION: 
X-Powered-By: soari-interceptors-4.4.4
Content-Type: text/plain
Cteonnt-Length: 77
Server: web
Content-Encoding: gzip
Content-Length: 89
Expires: Thu, 07 Jun 2018 09:48:25 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Thu, 07 Jun 2018 09:48:25 GMT
Connection: close

然后是上面的那些字符。注意Cteonnt -Length: 77标头,它不是我的 TYPO,它只是以这种方式出现的。

根据支持,他们使用以下标题成功并要求我使用它们,但我认为我所做的没有任何区别

WM_SVC.NAME:Walmart Marketplace
WM_QOS.CORRELATION_ID:123456abcdef
WM_SEC.AUTH_SIGNATURE:TnjevCf+voP9dmnafuCTFruwq6leBuAihSvag89WLieDRBsz7aULxgEqV71ZjIp572wVYPI07y6tdMutNLklDGwxvNdlJ2Q2xGvUIqjVPtqlhdcWvsmgqdpio7puQ4G03q1lReWzTquKecDEbB1ztH6ukj9F5rMe7d7PH8QkFsY=
WM_SEC.TIMESTAMP:1528152581896
WM_CONSUMER.ID:16248274-1f53-4e6d-880e-b5417698b878
WM_CONSUMER.CHANNEL.TYPE:0f3e4dd4-0514-4346-b39d-af0e00ea066d
Accept:application/xml
Host:marketplace.walmartapis.com
Content-Type:multipart/form-data

我已经与 eBay、Amazon、PayPal、Magento 等进行了成功的沟通,但显然我在这里遗漏了一些东西,真的不知道如何解决它。

感谢您阅读本文,希望有人能提供线索这里发生了什么。

编辑我正在根据需要添加一些 Delphi 代码

没有TIdMultipartFormDataStream 的版本 1

function TdmSyncWallmart.CreateItemFeed(aIDPlatforms: String; aLastChanged,
  aCurrDate: TDateTime; var aReqID: String): TStringStream;
var
  aXML: TNativeXML;
  aNode: TXmlNode;
  aItemNode: TXmlNode;
  aCatNode: TXmlNode;
  aTmpNode: TXmlNode;

  aShortDesc: String;
  i: Integer;
  aIDItems: String;
begin
  Result := nil;

  dstListPlatformsSyncItemsWallmart.Close;
  dstListPlatformsSyncItemsWallmart.Parameters.ParamByName('@IDPlatforms').Value := aIDPlatforms;
  dstListPlatformsSyncItemsWallmart.Parameters.ParamByName('@LastChanged').Value := aLastChanged;
  dstListPlatformsSyncItemsWallmart.Parameters.ParamByName('@CurrDate').Value := aCurrDate;
  dstListPlatformsSyncItemsWallmart.Open;

  if dstListPlatformsSyncItemsWallmart.IsEmpty then
    Exit;

  aReqID := GenGuid;

  aXML := TNativeXml.CreateName('MPItemFeed');
  try
    aXML.Declaration.AttributeAdd('standalone', 'yes');
    aXML.Root.AttributeAdd('xmlns:ns2', 'http://walmart.com/');

    //Header
    aNode := aXML.Root.NodeNew('MPItemFeedHeader');
    with aNode.NodeNew('version') do
      Value := '3.1';
    with aNode.NodeNew('requestId') do
      Value := aReqID;
    with aNode.NodeNew('mart') do
      Value := 'WALMART_US';

  //... some code for generating the XML
    Result := TStringStream.Create;
    aXML.XmlFormat := xfReadable;

    Result.WriteString('--qwerty'#13#10#13#10{'Content-Disposition: form-data; filename="wallmartreq.xml"'#13#10}+aXML.WriteToString +'--qwerty--'#13#10);
    Result.Position := 0;

  finally
    aXML.Free;
  end;
end;

function TdmSyncWallmart.CreateHTTP(aContentType: String): TIdHTTP;
begin
  Result := TIdHTTP.Create(nil);
  Result.ConnectTimeout:=5000;
  Result.ReadTimeout:=20000;
  Result.ProtocolVersion:=pv1_1;
  Result.HTTPOptions := [hoForceEncodeParams, hoKeepOrigProtocol];
  Result.HandleRedirects:=True;
  Result.IOHandler := SSLHandler;
  Result.Request.Accept:='application/xml, */*';
  Result.Request.AcceptLanguage:='en-US';
  Result.Request.ContentType:=aContentType;
//  Result.Request.CharSet:='utf-8';
  Result.Intercept := IdLogEvent1;
end;

procedure TdmSyncWallmart.AddCustomHeaders(aHTTP: TIdHTTP; aSign,
  aTimeStamp: String);
begin
  aHTTP.Request.CustomHeaders.AddValue('WM_SVC.NAME', 'Walmart Marketplace');
  aHTTP.Request.CustomHeaders.AddValue('WM_QOS.CORRELATION_ID', GenGuid);
  aHTTP.Request.CustomHeaders.AddValue('WM_SEC.TIMESTAMP', aTimeStamp);
  aHTTP.Request.CustomHeaders.AddValue('WM_SEC.AUTH_SIGNATURE', aSign);
  aHTTP.Request.CustomHeaders.AddValue('WM_CONSUMER.ID', dstPlatformsUserName.AsString);
  aHTTP.Request.CustomHeaders.AddValue('WM_CONSUMER.CHANNEL.TYPE', dstPlatformsPassword.AsString);
end;

//some code for debugging purposes
procedure TdmSyncWallmart.IdLogEvent1Send(ASender: TIdConnectionIntercept;
  var ABuffer: TIdBytes);
var
  aList: TStringList;
begin
  aList := TStringList.Create;
  try
    aList.Text := BytesToString(ABuffer);
    aList.SaveToFile('e:\wm_req_txt.txt');
  finally
    aList.Free;
  end;
end;

procedure TdmSyncWallmart.IdLogEvent1Receive(ASender: TIdConnectionIntercept;
  var ABuffer: TIdBytes);
var
  aList: TStringList;
begin
  aList := TStringList.Create;
  try
    aList.Text := BytesToString(ABuffer);
    aList.SaveToFile('e:\wm_Resp.txt');
  finally
    aList.Free;
  end;
end;

实际通话

procedure TdmSyncWallmart.SendItems(aIDPlatforms: String; aLastChanged,
  aCurrDate: TDateTime);
var
  aSign, aTimeStamp: String;
  aURL: String;
  aHTTP: TIdHTTP;
  aRes: String;
  aStrm: TMemoryStream;
  aReqID: String;

  aXML: TNativeXml;
  aNode: TXmlNode;

  aErrMsg: String;
begin
  aURL := dstPlatformsURLAddress.AsString+'/v3/feeds?feedType=item';
  GenrateSignature(aSign, aTimeStamp, aURL, 'POST');
  if aSign = '' then
    Exit;

  aHTTP := CreateHTTP('multipart/form-data;boundary=qwerty');
  AddCustomHeaders(aHTTP, aSign, aTimeStamp);
  try
    aStrm := CreateItemFeed(aIDPlatforms, aLastChanged, aCurrDate, aReqID);
    if aStrm <> nil then
    begin
      try
        aRes := TIdURI.URLDecode(aHTTP.Post(aURL, aStrm));

        aXML := TNativeXml.Create(nil);
        try
          aXML.ReadFromString(aRes);

          aNode := aXML.Root.FindNode('feedId');

          cmdUpdFeedID.Parameters.ParamByName('ID').Value := aRes;
          cmdUpdFeedID.Parameters.ParamByName('FeedID').Value := aNode.Value;
          cmdUpdFeedID.Execute;
        finally
          aXML.Free;
        end;
      except
        on E:Exception do
        begin
          if E is EIdHTTPProtocolException then
            aErrMsg := E.Message + #13#10 + (E as EIdHTTPProtocolException).ErrorMessage
          else
            aErrMsg := E.Message;

          dmMain.InsLog(cLTError, aErrMsg, aIDPlatforms);

        end;
      end;
      aStrm.Free;
    end;
  finally
    aHTTP.Free;
  end;
end;

编辑2

procedure TdmSyncWallmart.SendItems(aIDPlatforms: String; aLastChanged,
  aCurrDate: TDateTime);
var
  aSign, aTimeStamp: String;
  aURL: String;
  aHTTP: TIdHTTP;
  aRes: String;
  aStrm: TMemoryStream;
  aReqID: String;

  aXML: TNativeXml;
  aNode: TXmlNode;

  aErrMsg: String;

  aIdStream: TIdMultipartFormDataStream;
begin
  aURL := dstPlatformsURLAddress.AsString+'/v3/feeds?feedType=item';
  GenrateSignature(aSign, aTimeStamp, aURL, 'POST');
  if aSign = '' then
    Exit;

  aHTTP := CreateHTTP('multipart/form-data');
  AddCustomHeaders(aHTTP, aSign, aTimeStamp);
  try
    aStrm := TStringStream.Create();
    begin
      try
        aIdStream := TIdMultiPartFormDataStream.Create;
        aIdStream.AddFile('file', 'e:\wm_req.xml', 'multipart/form-data');
        aIdStream.Position := 0;
        astrm.LoadFromStream(aIdStream);

        aRes := TIdURI.URLDecode(aHTTP.Post(aURL, aStrm));

        aXML := TNativeXml.Create(nil);
        try
          aXML.ReadFromString(aRes);

          aNode := aXML.Root.FindNode('feedId');

          cmdUpdFeedID.Parameters.ParamByName('ID').Value := aRes;
          cmdUpdFeedID.Parameters.ParamByName('FeedID').Value := aNode.Value;
          cmdUpdFeedID.Execute;
        finally
          aXML.Free;
        end;
      except
        on E:Exception do
        begin
          if E is EIdHTTPProtocolException then
            aErrMsg := E.Message + #13#10 + (E as EIdHTTPProtocolException).ErrorMessage
          else
            aErrMsg := E.Message;

          dmMain.InsLog(cLTError, aErrMsg, aIDPlatforms);

        end;
      end;
      aStrm.Free;
    end;
  finally
    aHTTP.Free;
  end;
end;

这是发送的数据

----------060718213723831
Content-Disposition: form-data; name="file"; filename="wm_req.xml"
Content-Type: multipart/form-data
Content-Transfer-Encoding: binary

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<MPItemFeed xmlns:ns2="http://walmart.com/">
    <MPItemFeedHeader>
        <version>3.1</version>
        <requestId>{164726BF-288E-4953-A1DA-1EC7595C5725}</requestId>
        <mart>WALMART_US</mart>
    </MPItemFeedHeader>
    <MPItem>
        <processMode>REPLACE_ALL</processMode>
        <sku>w-cc-a1-4pk-white-l</sku>
        <productIdentifiers>
            <productIdentifier>
                <productIdType>UPC</productIdType>
                <productId>192082276845</productId>
            </productIdentifier>
        </productIdentifiers>
        <MPProduct>
        ..... the other part of the XML
        </MPProduct>
        <MPOffer>
            <price>25.00</price>
            <ShippingWeight>
                <measure>11.80</measure>
                <unit>lb</unit>
            </ShippingWeight>
            <ProductTaxCode>2038895</ProductTaxCode>
        </MPOffer>
    </MPItem>
</MPItemFeed>
----------060718213723831--

拦截部分捕获的返回数据与已经发布的相同Cteonnt-Length: 77标头,但我想如果我成功读取 gzip 数据,我会遇到可以转发给支持的错误。

HTTP/1.1 500 Internal Server Error
Method: null
URI: null
WM_CONSUMER.ID: 16248274-1f53-4e6d-880e-b5417698b878
WM_CONSUMER.INTIMESTAMP: 
WM_QOS.CORRELATION_ID: {CB0208AB-2135-4A12-B45F-DD2889273971}
WM_SEC.AUTH_TOKEN: 
WM_SEC.REFRESH_AUTH_TOKEN: 
WM_SVC.CLASS_NAME: com.walmart.services.impl.GMPGatewayService$$EnhancerBySpringCGLIB$$2ca3f3b6
WM_SVC.ENV: prod
WM_SVC.INTIMESTAMP: 1528396669253
WM_SVC.METHOD_NAME: doPostMultiPart
WM_SVC.NAME: Walmart Marketplace
WM_SVC.OUTTIMESTAMP: 1528396669365
WM_SVC.SERVER_IP: 10.65.34.2
WM_SVC.SERVER_NAME: PartnerGMPService-5480119-1-96141274
WM_SVC.VERSION: 
X-Powered-By: soari-interceptors-4.4.4
Content-Type: text/plain
Cteonnt-Length: 77
Server: web
Content-Encoding: gzip
Content-Length: 89
Vary: Accept-Encoding
Expires: Thu, 07 Jun 2018 18:37:49 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Thu, 07 Jun 2018 18:37:49 GMT
Connection: close

编辑3

对于我的 Edit1,我根本没有添加 Content-Disposition(它已被评论) - 有这么多测试,我把它留在了我的帖子中,很抱歉造成混淆。

对于 Edit2 - 感谢您指出这一点,实际上我在没有转换为 TStringStream 的情况下进行了第一次测试,但我想看看它们到底发生了什么。

无论如何,现在我直接使用了TIdMultipartFormDataStream并以这种方式更改了代码

    aIdStream := TIdMultiPartFormDataStream.Create;
    with aIdStream.AddFile('xml', 'e:\wm_req.xml', 'application/xml') do
    begin
      FileName := '';
      //ContentType := '';
      FileName := 'wmreq.xml';//somewhere I think I saw that only letters are allowed here
    end;
    aIdStream.Position := 0;

    aStrm := TMemoryStream.Create;

    //aRes := TIdURI.URLDecode(aHTTP.Post(aURL, aIdStream));
    aHTTP.Post(aURL, aIdStream, aStrm);

多亏了 Remy,我添加了 TIdCompressorZLib,现在我得到了有意义的错误:

HTTP/1.1 500 Internal Server Error No message body writer has found for response class FeedAcknowledgement。

我想这是来自他们,而不是来自我,需要与他们核实。

EDIT4解决方案

好吧,不管是否疯狂,也许是我的问题,但是一旦 Remy 说我不要求压缩答案并且他们发送给我这样的答案,我决定改为// Result.Request.Accept:='application/xml, */*';only// Result.Request.Accept:='application/xml';并且一切都开始正常工作!事实上,拥有*/*意味着我接受了一切,不是吗?无论您是使用 TIdMultipartFormDataStream 还是手动准备正文都没有关系,它可以正常工作。谢谢雷米的不同观点,另一双眼睛总是有帮助的。疯了……为期一周的愚蠢测试!

4

1 回答 1

2

在您的第一次编辑中,您没有TStringStream正确填充。改用这个:

Result.WriteString('--qwerty'#13#10{'Content-Disposition: form-data; name="file"; filename="wallmartreq.xml"'#13#10}#13#10 + aXML.WriteToString + #13#10'--qwerty--'#13#10);

在您的第二次编辑中,您提供了错误的 ContentType 到TIdMultipartFormDataStream.AddFile(). 您需要使用application/xml而不是multipart/form-data

aIdStream.AddFile('file', 'e:\wm_req.xml', 'application/xml');

或者,将 ContentType 留空(在这种情况下,application/octet-stream将改为使用):

aIdStream.AddFile('file', 'e:\wm_req.xml');

如果您根本不想发送 ContentType,可以将TIdFormDataField.ContentType属性设置为空字符串:

with aIdStream.AddFile('file', 'e:\wm_req.xml') do
begin 
  FileName := ''; // needed so ContentType setter will not use a default value...
  ContentType := '';
  FileName := 'wm_req.xml'; // or whatever you want, or leave blank...
end;

但是,更重要的是,您不再为标头指定boundary属性。TIdHTTP.Request.ContentType实际上,您根本不应该将 a 保存TIdMultipartFormDataStream到 aTStringStream然后再发布TStringStream。你应该发布它TIdMultipartFormDataStream本身。这将自动将 设置TIdHTTP.Request.ContentTypemultipart/form-data,并为其提供正确的boundary属性(其值由 生成TIdMultipartFormDataStream):

aHTTP.Post(aURL, aIdStream)

现在,话虽如此,在这两种情况下,您都需要删除对TIdURI.URLDecode()返回值的调用TIdHTTP.Post()。服务器应该向您发送原始XML,而不是 URL 编码的 XML,因此您需要按原样处理 XML,而不是对它进行 URL 解码。

此外,由于 XML 在技术上是二进制数据,可以编码为任何字符集,这些字符集可能存在也可能不存在于 HTTP 响应标头中,因此您应该让 XML 解析器完全按照服务器发送的 XML 进行处理。为此,请使用TIdHTTP.Post()填充 aTStream而不是返回 a的重载版本String。让它将服务器的 XML 接收到 aTMemoryStream中,然后将该流加载到您的解析器中(TNativeXml有一个LoadFromStream()方法)。


最后,您显示服务器的响应具有Content-Encoding: gzip响应标头,但我没有看到您将任何对象分配给TIdHTTP.Compressor属性,或手动设置TIdHTTP.Request.AcceptEncoding属性,因此服务器不应该以压缩格式发送响应正文,因为您不是要求这种格式。 TIdHTTP不会自动解压没有Compressor指定的数据。

如果服务器真的在没有被询问的情况下发送压缩数据,那是服务器端的一个错误,您应该向沃尔玛报告。

于 2018-06-07T19:16:18.200 回答