首页 文章

将多部分表单发布到Bamboo API

提问于
浏览
11

通过VB.NET控制台应用程序向BambooHR API提交多部分表单我遇到了很多困难 . 我发布了当前代码以及下面文档中的示例请求,当我运行此代码时,我得到(400)错误请求 . 我知道代码很乱,但我一直试图让它工作 .

我能够通过使用他们的示例代码来使GET请求工作,但他们没有任何代码来执行此特定的API调用(上传员工文件) .

任何帮助,将不胜感激 .

这是我的代码:

Sub Main()

    upload(id, "https://api.bamboohr.com/api/gateway.php/company")

    Console.WriteLine()
    Console.WriteLine("Press ENTER to quit")
    Console.ReadLine()
End Sub

Function upload(ByVal employeeId As Integer, ByVal baseUrl As String)

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 Or SecurityProtocolType.Ssl3

    Dim boundary = "----BambooHR-MultiPart-Mime-Boundary----"
    Dim url = String.Format("{0}/v1/employees/{1}/files/", baseUrl, employeeId)

    Dim request As HttpWebRequest = WebRequest.Create(url)
    request.KeepAlive = True
    request.Method = "POST"
    request.ContentType = "multipart/form-data; boundary=" + boundary

    'Authorization is just the api key and a random string, in this case is x
    '
    Dim authInfo As String = api_key + ":" + "x"
    authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo))
    request.Headers("Authorization") = "Basic " + authInfo


    Dim memStream As New MemoryStream()

    WriteMPF(memStream)

    request.ContentLength = memStream.Length

    Using requestStream = request.GetRequestStream()
        memStream.Position = 0
        Dim tempBuffer As Byte() = New Byte(memStream.Length - 1) {}
        memStream.Read(tempBuffer, 0, tempBuffer.Length)
        memStream.Close()
        requestStream.Write(tempBuffer, 0, tempBuffer.Length)
    End Using

    Dim webresponse As HttpWebResponse = request.GetResponse()
    Return webresponse

End Function

Private Sub WriteMPF(s As Stream)

    WriteToStream(s, "POST /api/gateway.php/company/v1/employees/id/files/ HTTP/1.0")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Host: api.bamboohr.com")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Content-Type: multipart/form-data; boundary=----BambooHR-MultiPart-Mime-Boundary----")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Content-Length: 520")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, vbCr & vbLf)

    WriteToStream(s, "------BambooHR-MultiPart-Mime-Boundary----")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Content-Disposition: form-data; name=""category""")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "14")
    WriteToStream(s, vbCr & vbLf)

    WriteToStream(s, "------BambooHR-MultiPart-Mime-Boundary----")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Content-Disposition: form-data; name=""fileName""")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "test.txt")
    WriteToStream(s, vbCr & vbLf)

    WriteToStream(s, "------BambooHR-MultiPart-Mime-Boundary----")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Content-Disposition: form-data; name=""share""")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "no")
    WriteToStream(s, vbCr & vbLf)

    WriteToStream(s, "------BambooHR-MultiPart-Mime-Boundary----")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Content-Disposition: form-data; name=""file""; filename = ""test.txt""")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "Content-Type: text/plain")
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "this is a test!")
    WriteToStream(s, vbCr & vbLf)

    WriteToStream(s, vbCr & vbLf)
    WriteToStream(s, "------BambooHR-MultiPart-Mime-Boundary------")
    WriteToStream(s, vbCr & vbLf)
End Sub

Private Sub WriteToStream(s As Stream, txt As String)
    Dim bytes As Byte() = Encoding.UTF8.GetBytes(txt)
    s.Write(bytes, 0, bytes.Length)
End Sub

以下是文档中的示例请求:(链接:https://www.bamboohr.com/api/documentation/employees.php向下滚动到"Upload an Employee File")

POST /api/gateway.php/sample/v1/employees/1/files/ HTTP / 1.0主机:api.bamboohr.com内容类型:multipart / form-data; boundary = ---- BambooHR-MultiPart-Mime-Boundary ---- Content-Length:520

------ BambooHR-MultiPart-Mime-Boundary ---- Content-Disposition:form-data; NAME = “类别”

112 ------ BambooHR-MultiPart-Mime-Boundary ---- Content-Disposition:form-data; NAME = “文件名”

readme.txt ------ BambooHR-MultiPart-Mime-Boundary ---- Content-Disposition:form-data; NAME = “分享”

是的------ BambooHR-MultiPart-Mime-Boundary ---- Content-Disposition:form-data; NAME = “文件”; filename =“readme.txt”Content-Type:text / plain

这是一个示例文本文件 .

------ BambooHR-多部分MIME-边界------

2 回答

  • 1

    在他们的GitHub上使用php示例并将其复制到VB.NET . 这有点乱,但它确实有效 . 这是相关代码:

    Public Function sendRequestMPF(ByVal req As BambooHTTPRequest, ByVal fileLocation As String) As BambooHTTPResponse
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 Or SecurityProtocolType.Ssl3
    
            Dim request As HttpWebRequest = WebRequest.Create(req.url)
            request.Method = req.method
            request.Host = "api.bamboohr.com"
    
            Dim boundary = "----BambooHR-MultiPart-Mime-Boundary----"
    
            Try
                request.ContentType = "multipart/form-data; boundary=" + boundary
                request.ContentLength = req.contents.Length
            Catch ex As Exception
    
            End Try
    
            Dim iCount As Integer = req.headers.Count
            Dim key As String
            Dim keyvalue As String
    
            Dim i As Integer
            For i = 0 To iCount - 1
                key = req.headers.Keys(i)
                keyvalue = req.headers(i)
                request.Headers.Add(key, keyvalue)
            Next
    
            Dim enc As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()
            Dim bytes() As Byte = {}
            Dim pdfBytes() As Byte = {}
            Dim lBytes() As Byte = {}
    
            Dim fBytes() As Byte = {}
            Dim s As New MemoryStream()
    
            If (req.contents.Length > 0) Then
                bytes = enc.GetBytes(req.contents)
                s.Write(bytes, 0, bytes.Length)
    
                pdfBytes = File.ReadAllBytes(fileLocation)
                s.Write(pdfBytes, 0, pdfBytes.Length)
    
                Dim postHeader = vbCrLf + vbCrLf + "--" + boundary + "--" + vbCrLf
                Dim postHeaderBytes() As Byte = enc.GetBytes(postHeader)
                lBytes = enc.GetBytes(postHeader)
                s.Write(postHeaderBytes, 0, postHeaderBytes.Length)
    
                fBytes = s.ToArray()
                request.ContentLength = fBytes.Length
            End If
    
            request.AllowAutoRedirect = False
    
            If Not basicAuthUsername.Equals("") Then
                Dim authInfo As String = basicAuthUsername + ":" + basicAuthPassword
                authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo))
                request.Headers("Authorization") = "Basic " + authInfo
            End If
    
            If req.contents.Length > 0 Then
                Dim outBound As Stream = request.GetRequestStream()
                outBound.Write(fBytes, 0, fBytes.Length)
            End If
    
            Dim resp As BambooHTTPResponse
            Try
                Dim webresponse As HttpWebResponse = request.GetResponse()
                resp = New BambooHTTPResponse(webresponse)
                resp.responseCode = webresponse.StatusCode
                resp.headers = webresponse.Headers
            Catch e As WebException
                Console.WriteLine(e.Message)
                If (e.Status = WebExceptionStatus.ProtocolError) Then
                    resp = New BambooHTTPResponse(DirectCast(e.Response, HttpWebResponse).StatusCode)
                Else
                    resp = New BambooHTTPResponse(0)
                End If
            End Try
    
            Return resp
        End Function
    
    Public Function buildMultiPart(ByVal params As NameValueCollection, ByVal boundary As String, ByVal contentType As String, ByVal name As String, ByVal fileName As String)
            Dim data = ""
    
            For Each key In params.AllKeys
                data += "--" + boundary + vbCrLf
                data += "Content-Disposition: form-data; name=""" + key + """"
                data += vbCrLf + vbCrLf
                data += params(key) + vbCrLf
            Next
    
            data += "--" + boundary + vbCr + vbLf
            data += "Content-Disposition: form-data; name=""" + name + """;" + " filename=""" + fileName + """" + vbCrLf
            data += "Content-Type: " + contentType + vbCrLf
            data += vbCrLf
            'data += fileData + vbCrLf + vbCrLf
            'data += "--" + boundary + "--" + vbCrLf
    
            Return data
        End Function
    
        Public Function uploadEmployeeFile(ByVal employeeId As Integer, ByVal fileName As String, ByVal fileLocation As String)
            Dim request As New BambooHTTPRequest()
            request.url = String.Format("{0}/v1/employees/{1}/files/", Me.baseUrl, employeeId)
            request.method = "POST"
    
            Dim boundary = "----BambooHR-MultiPart-Mime-Boundary----"
    
            Dim params = New NameValueCollection
            params.Add("category", "13")
            params.Add("fileName", fileName)
            params.Add("share", "no")
    
            request.contents = buildMultiPart(params, boundary, "application/pdf", "file", fileName)
    
            Return http.sendRequestMPF(request, fileLocation)
        End Function
    

    所需的其余代码可以在他们的GitHub上找到https://github.com/BambooHR

  • 3

    我怀疑至少你的_1143833会错 . 该内容长度仅适用于他们的示例 .

    无论如何,我很长一段时间没有编写过VB.Net,但是通过快速测试,这个代码的修改版本可以对付我的一个REST服务,所以它应该适用于你的情况,可能还有一些小的调整 .

    我的测试控制台项目使用.Net 4.6.1,但可能会与早期的.Net框架一起运行 .

    Imports System.IO
    Imports System.Net.Http
    
    Module Module1
    
        Sub Main()
            Call UploadFileToWebsite(14, "no", "D:\Temp\file.pdf")
            Console.WriteLine("Please wait for a response from the server and then press a key to continue.")
            Console.ReadKey()
        End Sub
    
        Public Sub UploadFileToWebsite(category As Integer, share As String, file As String)
            Dim message = New HttpRequestMessage()
            Dim content = New MultipartFormDataContent()
    
            content.Add(New StringContent(category.ToString()), "category")
            content.Add(New StringContent(share), "share")
    
            Dim filestream = New FileStream(file, FileMode.Open)
            Dim fileName = System.IO.Path.GetFileName(file)
    
            content.Add(New StreamContent(filestream), "file", fileName)
    
            message.Method = HttpMethod.Post
            message.Content = content
            message.RequestUri = New Uri("https://api.bamboohr.com/api/gateway.php/company")
    
            Dim client = New HttpClient()
            client.SendAsync(message).ContinueWith(
                Sub(task)
                    'do something with response
                    If task.Result.IsSuccessStatusCode Then
                        Console.WriteLine("Uploaded OK.")
                    Else
                        Console.WriteLine("Upload Failed.")
                    End If
                End Sub)
        End Sub
    End Module
    

    在不相关的注释中,您也可以使用 vbCrLf 而不是 vbCr & vbLf .

相关问题