XML请求附件丢失

时间:2014-05-08 19:23:01

标签: xml base64 attachment multipartform-data ebay

我正在尝试使用API​​调用UploadSiteHostedPictures将图像上传到eBay的服务器。

该调用允许发送URL或二进制数据。对于我的应用程序,我选择使用后者来避免因eBay无法通过HTTPS读取数据而导致的问题。


我的要求

接头

  • 内容类型 multipart / form-data;边界= abcdefghijklmnopqrstuv0987654321
  • X-EBAY-API-DEV-NAME DEV_NAME
  • X-EBAY-API-APP-NAME APP_NAME
  • X-EBAY-API-CERT-NAME CERT_NAME
  • X-EBAY-API-SITEID SITEID
  • X-EBAY-API-COMPATIBILITY-LEVEL 863

车身

--abcdefghijklmnopqrstuv0987654321
Content-Disposition: form-data; name="XML Payload"
Content-Type: text/xml;charset=utf-8"

<?xml version="1.0" encoding="utf-8"?>
<UploadSiteHostedPicturesRequest xmlns="urn:ebay:apis:eBLBaseComponents">
  <RequesterCredentials>
    <eBayAuthToken>token</eBayAuthToken>
  </RequesterCredentials>
</UploadSiteHostedPicturesRequest>
--abcdefghijklmnopqrstuv0987654321
Content-Disposition: form-data; name="imgname"; filename="imgname"
Content-Transfer-Encoding: base64
Content-Type: application/octet-stream

photo base64binary data
--abcdefghijklmnopqrstuv0987654321--

Ebay的回应

<?xml version="1.0" encoding="UTF-8"?>
<UploadSiteHostedPicturesResponse xmlns="urn:ebay:apis:eBLBaseComponents">
  <Timestamp>2014-05-08T18:31:03.633Z</Timestamp>
  <Ack>Failure</Ack>
  <Errors>
    <ShortMessage>Attachment request file is missing.</ShortMessage>
    <LongMessage>Attachment request file is missing.</LongMessage>
    <ErrorCode>2191116</ErrorCode>
    <SeverityCode>Error</SeverityCode>
    <ErrorClassification>RequestError</ErrorClassification>
  </Errors>
  <Version>871</Version>
  <Build>E871_CORE_MSA_16805861_R1</Build>
</UploadSiteHostedPicturesResponse>

1 个答案:

答案 0 :(得分:1)

这是我的.net版本。对不起它是vb .. Telerik这是一个很棒的免费在线工具。 (http://converter.telerik.com/

响应

Public Class UploadSiteHostedPicture_APIResponse

Private _APICallLength As Integer
''' <summary>
''' This is the time in milliseconds that it took for the API call to respond.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property APICallLength() As Integer
    Get
        Return _APICallLength
    End Get
    Set(ByVal value As Integer)
        _APICallLength = value
    End Set
End Property

Public Property APIStatus() As String
Public Property Success As Boolean = False

Public Property APICallStartTime As DateTime
Public Property APICallEndTime As DateTime

Public Property FullResponse As String

Public Property SiteHostedPictureDetail As New SiteHostedPictureDetails

Public Property ExternalPictureURL As String
Public Property UseByDate As DateTime

Public Property Errors As Boolean = False
Public Property ErrorMsgShort As String
Public Property ErrorMsgLong As String

Public Class SiteHostedPictureDetails
    Public Property PictureSet As String
    Public Property PictureFormat As String
    Public Property FullURL As String
    Public Property BaseURL As String
    Public Property ExternalPictureURL As String

    Public Property PictureSetMembers As New List(Of PictureSetMember)

    Public Class PictureSetMember
        Public Property MemberURL As String
        Public Property PictureHeight As Integer
        Public Property PictureWidth As Integer
    End Class

End Class

请求

Imports System.Xml.XPath
Imports System.IO
Imports System.Net
Imports System.Text
Imports System.Configuration

Public Class UploadSiteHostedPicture_APIRequest

'http://developer.ebay.com/DevZone/XML/docs/Reference/eBay/UploadSiteHostedPictures.html
'http://iweb.corp.ebay.com/prod/help/API/doc_internal/xml/Reference/ebay/DeleteSiteHostedPictures.html

#Region "Private Init Items"

Private _DevID As String = ""
Private _AppID As String = ""
Private _CertID As String = ""
Private _ServiceEndpoint As String = ""
Private _AuthToken As String = ""

Private SERVER_NAME As String = ConfigurationManager.AppSettings("Host_Name")
Private SCRIPT_NAME As String = SERVER_NAME & "/UploadSiteHostedPicture_APIRequest.vb"

Private _ExtensionDays As Integer = -1 'Need to set this to a value >=0 for it to be added into the request.
Private _BoundaryText As String = "file_boundary_tag"
Private _APICallStartTime As DateTime
Private _APICallEndTime As DateTime

#End Region

#Region "Public Items"

Public Property RawResponse As String

Public Sub New(DevID As String, AppID As String, CertID As String, ServiceEndpoint As String, AuthToken As String)
    _DevID = DevID
    _AppID = AppID
    _CertID = CertID
    _ServiceEndpoint = ServiceEndpoint
    _AuthToken = AuthToken
End Sub

''' <summary>
''' Allows you to pass in the remote url of the image for the eBay service to download and process.
''' </summary>
''' <param name="RemoteImageUrl">Remote URL of the image that the image service needs to download</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetAPIValue(RemoteImageUrl As String) As UploadSiteHostedPicture_APIResponse
    Dim retVal As New UploadSiteHostedPicture_APIResponse()
    _APICallStartTime = Now()
    Dim respString As String = getAPIResponse(RemoteImageUrl)
    _APICallEndTime = Now()

    If (respString = "") Then
    Else
        retVal = ProcessResponse(respString)
    End If
    Return retVal
End Function

''' <summary>
''' Allows you to pass in a byte array with the image data.
''' </summary>
''' <param name="RawImageData">A byte array of the image to post to the eBay image service</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetAPIValue(RawImageData As Byte()) As UploadSiteHostedPicture_APIResponse
    Dim retVal As New UploadSiteHostedPicture_APIResponse()
    _APICallStartTime = Now()
    Dim respString As String = getAPIResponse(RawImageData)
    _APICallEndTime = Now()

    If (respString = "") Then
    Else
        retVal = ProcessResponse(respString)
    End If

    Return retVal
End Function

#End Region

#Region "Private Processing Methods"

''' <summary>
''' Private function to add the necessary headers to the WebRequest
''' </summary>
''' <param name="RemoteURLInUse">Setting this to FALSE means that you are posting binary image data and the method will add the necessary ContentType values to the WebRequest</param>
''' <returns>A new HttpWebRequest object</returns>
''' <remarks></remarks>
Private Function getWebRequest(RemoteURLInUse As Boolean) As HttpWebRequest
    Dim req As HttpWebRequest = DirectCast(WebRequest.Create(_ServiceEndpoint), HttpWebRequest)

    'Add the request headers
    req.Headers.Add("X-EBAY-API-COMPATIBILITY-LEVEL", "803")
    'req.Headers.Add("X-EBAY-API-SITEID", "0")  'US SiteID
    req.Headers.Add("X-EBAY-API-SITEID", "15") 'AU SiteID
    req.Headers.Add("X-EBAY-API-CALL-NAME", "UploadSiteHostedPictures")
    req.Headers.Add("X-EBAY-API-DEV-NAME", _DevID)
    req.Headers.Add("X-EBAY-API-APP-NAME", _AppID)
    req.Headers.Add("X-EBAY-API-CERT-NAME", _CertID)

    req.Method = "POST"

    If (RemoteURLInUse = False) Then
        req.ContentType = "multipart/form-data; boundary=" & _BoundaryText
    End If

    Return req
End Function

''' <summary>
''' Gets the raw response from the API when a remote image url is passed in.
''' </summary>
''' <param name="RemoteImageUrl">The url of the image that the eBay image service will need to download</param>
''' <returns></returns>
''' <remarks></remarks>
Private Function getAPIResponse(RemoteImageUrl As String) As String
    Dim retVal As HttpWebResponse = Nothing
    Dim req As HttpWebRequest = getWebRequest(True)
    Dim strRequest As New StringBuilder("")

    strRequest.Append("<?xml version=""1.0"" encoding=""utf-8""?>")
    strRequest.Append("<UploadSiteHostedPicturesRequest xmlns=""urn:ebay:apis:eBLBaseComponents"">")
    If _ExtensionDays >= 0 Then
        strRequest.Append(" <ExtensionInDays>" & _ExtensionDays & "</ExtensionInDays>")
    End If
    strRequest.Append(" <ExternalPictureURL>" & RemoteImageUrl & "</ExternalPictureURL>")
    strRequest.Append(" <RequesterCredentials>")
    strRequest.Append("  <eBayAuthToken>" & _AuthToken & "</eBayAuthToken>")
    strRequest.Append(" </RequesterCredentials>")
    strRequest.Append("</UploadSiteHostedPicturesRequest>")

    Dim postDataBytes As Byte() = System.Text.Encoding.ASCII.GetBytes(strRequest.ToString())
    Dim len As Integer = postDataBytes.Length
    req.ContentLength = len

    Dim requestStream As System.IO.Stream = req.GetRequestStream()
    requestStream.Write(postDataBytes, 0, len)
    requestStream.Close()

    Try
        ' get response and write to console
        retVal = DirectCast(req.GetResponse(), HttpWebResponse)
    Catch ex As Exception

    End Try

    Return getWebResponseString(retVal)
End Function

''' <summary>
''' Gets the raw response from the API when the raw image data is passed in.
''' </summary>
''' <param name="ImageData">A byte array containing the image file data</param>
''' <returns></returns>
''' <remarks></remarks>
Private Function getAPIResponse(ImageData As Byte()) As String
    Dim retVal As HttpWebResponse = Nothing

    Dim req As HttpWebRequest = getWebRequest(False)

    Dim uploadFileRequest As String

    Dim sb As New StringBuilder()
    sb.AppendLine("--" & _BoundaryText)
    sb.AppendLine("Content-Disposition: form-data; name=""XML Payload""")
    sb.AppendLine("Content-Type: text/plain; charset=US-ASCII")
    sb.AppendLine("Content-Transfer-Encoding: 8bit")
    sb.AppendLine("")
    sb.AppendLine("<?xml version=""1.0"" encoding=""utf-8""?>")
    sb.AppendLine("<UploadSiteHostedPicturesRequest xmlns=""urn:ebay:apis:eBLBaseComponents"">")
    If _ExtensionDays >= 0 Then
        sb.AppendLine(" <ExtensionInDays>" & _ExtensionDays & "</ExtensionInDays>")
    End If
    sb.AppendLine(" <RequesterCredentials>")
    sb.AppendLine("  <ebl:eBayAuthToken xmlns:ebl=""urn:ebay:apis:eBLBaseComponents"">" & _AuthToken & "</ebl:eBayAuthToken>")
    sb.AppendLine(" </RequesterCredentials>")
    sb.AppendLine(" <PictureSet>Supersize</PictureSet>")
    sb.AppendLine("</UploadSiteHostedPicturesRequest>")
    sb.AppendLine("")
    sb.AppendLine("--" & _BoundaryText)
    sb.AppendLine("Content-Type: application/octet-stream; charset=ISO-8859-1")
    sb.AppendLine("Content-Transfer-Encoding: binary")
    sb.AppendLine("")
    uploadFileRequest = sb.ToString()
    Dim postDataBytes1 As Byte() = System.Text.Encoding.UTF8.GetBytes(uploadFileRequest)

    Dim postDataBytes2 As Byte() = System.Text.Encoding.UTF8.GetBytes(vbCrLf & "--" & _BoundaryText & "--" & vbCrLf)

    Dim len As Integer = postDataBytes1.Length + ImageData.Length + postDataBytes2.Length
    req.ContentLength = len

    Dim requestStream As System.IO.Stream = req.GetRequestStream()
    requestStream.Write(postDataBytes1, 0, postDataBytes1.Length)
    requestStream.Write(ImageData, 0, ImageData.Length)
    requestStream.Write(postDataBytes2, 0, postDataBytes2.Length)
    requestStream.Close()
    retVal = DirectCast(req.GetResponse(), HttpWebResponse)

    Return getWebResponseString(retVal)
End Function

''' <summary>
''' Returns the WebResponse as a string
''' </summary>
''' <param name="resp"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function getWebResponseString(resp As HttpWebResponse) As String
    Dim retVal As String
    Dim responseReader As New StreamReader(resp.GetResponseStream(), Encoding.UTF8)
    retVal = responseReader.ReadToEnd()
    resp.Close()
    Return retVal
End Function

''' <summary>
''' Processess the response from the API and returns a typed object of UploadSiteHostedPicture_APIResponse
''' </summary>
''' <param name="strResponse">The response string from the API</param>
''' <returns></returns>
''' <remarks></remarks>
Private Function ProcessResponse(strResponse As String) As UploadSiteHostedPicture_APIResponse
    Dim retVal As New UploadSiteHostedPicture_APIResponse

    strResponse = strResponse.Replace("<?xml version='1.0' encoding='UTF-8'?>", "").Replace("<?xml version=""1.0"" encoding=""UTF-8""?>", "").Replace(" xmlns=""urn:ebay:apis:eBLBaseComponents""", "")
    retVal.FullResponse = strResponse

    Using stream = New StringReader(strResponse)
        Dim doc As XPathDocument = New XPathDocument(stream)
        Dim nav As XPathNavigator = doc.CreateNavigator()
        Dim strException As String = SCRIPT_NAME & " | ProcessResponse() | "
        'Check for successfull call
        nav = nav.SelectSingleNode("/UploadSiteHostedPicturesResponse")

        If (Not IsNothing(nav)) Then

            With retVal
                .APIStatus = getXPathValue(nav.SelectSingleNode("//Ack"))

                .ErrorMsgShort = getXPathValue(nav.SelectSingleNode("//ShortMessage")).ToString.Trim
                .ErrorMsgLong = getXPathValue(nav.SelectSingleNode("//LongMessage")).ToString.Trim
                If .APIStatus = "Failure" Then
                    .Success = False
                    .Errors = True
                    'Logging.Log(Logging.LogLevel.Warn, SCRIPT_NAME & " | ProcessResponse | API ERROR", New Exception("API Call Error - " & .ErrorMsgShort))
                Else
                    .Success = True
                    nav = nav.SelectSingleNode("//SiteHostedPictureDetails")
                    With .SiteHostedPictureDetail
                        .PictureSet = getXPathValue(nav.SelectSingleNode("PictureSet"))
                        .PictureFormat = getXPathValue(nav.SelectSingleNode("PictureFormat"))
                        .FullURL = getXPathValue(nav.SelectSingleNode("FullURL"))
                        .BaseURL = getXPathValue(nav.SelectSingleNode("BaseURL"))
                        .ExternalPictureURL = getXPathValue(nav.SelectSingleNode("ExternalPictureURL"))

                        Dim psm As XPathNodeIterator = nav.Select("PictureSetMember")
                        For Each node As XPathNavigator In psm
                            Dim NewPSM As New UploadSiteHostedPicture_APIResponse.SiteHostedPictureDetails.PictureSetMember()
                            With NewPSM
                                .MemberURL = getXPathValue(node.SelectSingleNode("MemberURL"))
                                .PictureHeight = cInt(getXPathValue(node.SelectSingleNode("PictureHeight")))
                                .PictureWidth = cInt(getXPathValue(node.SelectSingleNode("PictureWidth")))
                            End With
                            .PictureSetMembers.Add(NewPSM)
                        Next
                    End With
                End If
                .APICallStartTime = _APICallStartTime
                .APICallEndTime = _APICallEndTime
            End With

        End If

    End Using

    Return retVal
End Function

#End Region

#Region "Private Helper Functions"

''' <summary>
''' Gets the XPathValue
''' </summary>
''' <param name="strValue"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function getXPathValue(strValue As XPathNavigator) As String
    If (Not strValue Is Nothing) Then
        Return strValue.Value
    End If
    Return Nothing
End Function

#End Region

End Class