我在通过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向下滚动到“上传员工文件”)]
POST /api/gateway.php/sample/v1/employees/1/files/ HTTP / 1.0主持人:api.bamboohr.com内容类型:多部分/表单数据;边界= ---- BambooHR-MultiPart-Mime-边界----内容长度:520
------ BambooHR-MultiPart-Mime-Boundary ----内容处置:表格数据; name =“ category”
112------ BambooHR-MultiPart-Mime-Boundary ----内容处置:表格数据; name =“ fileName”
readme.txt------ BambooHR-MultiPart-Mime-Boundary ----内容处置:表格数据; name =“ share”
是------ BambooHR-MultiPart-Mime-Boundary ----内容处置:表格数据; name =“文件”; filename =“ readme.txt”内容类型:文本/纯文本
这是示例文本文件。
------ BambooHR-MultiPart-Mime-Boundary ------
[在其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中找到
我怀疑至少您的Content-Length: 520
是错误的。内容长度仅适用于他们的示例。
不管怎么说,我已经很长时间没有编写VB.Net了,但是通过快速测试,这段代码的修改后的版本可以与我的REST服务配合使用,因此它应该可以在您的情况下使用,也许有些小调整。
我的测试控制台项目使用.Net 4.6.1,但可能会与某些早期的.Net Frameworks一起运行。
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
。
是否有人愿意分享有关从BambooHR下载用户文档的代码段?我可以打电话查看与用户关联的每个文件返回的xml,但是我无法使下载正常工作。
我正在尝试找到一种为每个用户导出数据的方法。
先谢谢您。