The short of this is that I need to send a byte[]
array as a body value. The problem is that [FromBody]
is always null. All of the solutions I have seen so far involve the passed value going to a string in one way or another. This is fine if the original content being passed is plain text (ascii) but in cases where I'm sending (for example) a jpg, this doesn't work.
It is extremely important to realize and know that I CANNOT use HTTPClient as adding it in any form for some reason breaks the solution in all kinds of places. I am stuck using WebClient.
Here is the code I have below:
Calling page:
Private Function UploadFile(targetURL As String, fileAttachment As Byte()) As String
Dim retVal As String = String.Empty
Using client = New WebClient()
Try
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(targetURL), HttpWebRequest)
request.Method = "POST"
request.ContentType = "application/x-www-form-urlencoded"
request.ContentLength = fileAttachment.Length
Dim requestStream As Stream = request.GetRequestStream()
requestStream.Write(fileAttachment, 0, fileAttachment.Length)
Dim response As WebResponse = request.GetResponse()
Dim respStream As Stream = response.GetResponseStream()
Dim reader As New StreamReader(respStream)
retVal = reader.ReadToEnd()
respStream.Dispose()
reader.Dispose()
Catch ex As WebException
If ex.Status = WebExceptionStatus.ProtocolError Then
Dim wbrsp As HttpWebResponse = CType(ex.Response, HttpWebResponse)
Throw New HttpException(CInt(wbrsp.StatusCode), wbrsp.StatusDescription)
Else
Throw New HttpException(500, ex.Message)
End If
End Try
End Using
Return retVal
End Function
WebAPI method:
[Route("Upload/{appName}/{appKey}/{fileName}/{fileExt}")]
public async Task<string> Post(string appName, string appKey, string fileName, string fileExt, [FromBody] byte[] values) {
//snip as rest is not needed since values is always null
What would be a reasonable solution so that the byte array is not converted to a string (which has the effect of "corrupting" the values)?
The solution to this was counter-intuitive:
//targetURL As String, fileAttachment As Byte(), fileName As String, fileExtension As String
//you don't send the data to the webapi action. You WRITE to it like it's a file
Using client = New WebClient()
Try
client.Headers.Add("Content-Type", "application/octet-stream")
Using requestStream As Stream = client.OpenWrite(New Uri(targetURL), "POST")
requestStream.Write(fileAttachment, 0, fileAttachment.Length)
End Using
Catch ex As WebException
If ex.Status = WebExceptionStatus.ProtocolError Then
Dim wbrsp As HttpWebResponse = CType(ex.Response, HttpWebResponse)
Throw New HttpException(CInt(wbrsp.StatusCode), wbrsp.StatusDescription)
Else
Throw New HttpException(500, ex.Message, New Exception("File upload failed."))
End If
End Try
End Using
And the magic code for the WebAPI:
byte[] values = await Request.Content.ReadAsByteArrayAsync();
You don't think of sending data to a URL the way you'd write to a file because you just don't do things that way but it works and the byte stream is not converted into a string anywhere in the process (which keeps the stream from being "corrupted" if the source isn't plain ascii.
Of course the big problem with this is that no matter how you set up the WebAPI action to return data, the OpenWrite method doesn't return anything. So all you can do is throw an exception if something borks. If you need data returned, you'll simply have to write another action to retrieve data created from your first call (in this case, a unique id for the file uploaded and saved).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.