Как использовать WebClient для публикации в WebAPI с помощью [FromBody]

Короче говоря, мне нужно отправить byte[]массив в качестве значения тела. Проблема в том, что [FromBody]это всегда null. Все решения, которые я видел до сих пор, включают в себя переданное значение, переходящее в строку тем или иным образом. Это нормально, если исходное содержимое передается простым текстом (ascii), но в случаях, когда я отправляю (например) jpg, это не работает.

Чрезвычайно важно понимать и знать, что я не могу использовать HTTPClient, так как добавление его в любой форме по какой-то причине нарушает решение во всех местах. Я застрял с помощью WebClient.

Вот код, который я имею ниже:

Вызывающая страница:

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:

    [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

Каким было бы разумное решение, чтобы массив байтов не преобразовывался в строку (что приводит к «порче» значений)?

1 ответ

  1. Решение этой проблемы было интуитивно понятным:

    //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
    

    И волшебный код для WebAPI:

    byte[] values = await Request.Content.ReadAsByteArrayAsync(); 
    

    Вы не думаю, что отправка данных на URL-адрес, как вы пишете в файл, потому что вы просто не делать это таким образом , но это работает и в байтовый поток не преобразуется в строку в любом месте в процессе (который держит поток могут быть «повреждены» если источник не в ASCII.

    Конечно, большая проблема с этим заключается в том, что независимо от того, как вы настраиваете действие WebAPI для возврата данных, метод OpenWrite ничего не возвращает. Поэтому все, что вы можете сделать, это создать исключение, если что-то борется. Если вам нужно вернуть данные, вам просто нужно будет написать другое действие, чтобы получить данные, созданные при первом вызове (в этом случае уникальный идентификатор загруженного и сохраненного файла).