簡體   English   中英

將音頻(字節數組)發布到 MVC.NET Web Api

[英]Posting Audio (byte array) to MVC.NET Web Api

問題

我正在嘗試將我的 android 設備錄制的音頻發送到 MVC.NET Web Api。 我通過傳遞簡單的字符串參數確認了連接。 但是,當我嘗試傳遞從音頻生成的字節數組時,每次都從服務器獲得 500。 我嘗試了多種配置,但這是我目前擁有的:

MVC Web API

public class PostParms
{
    public string AudioSource { get; set; }
    public string ExtraInfo { get; set; }
}

public class MediaController : ApiController
{
    [HttpPost]
    public string Post([FromBody]PostParms parms)
    {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(parms.AudioSource);
        return "success";
    }
}

安卓代碼

public class WebServiceTask extends AsyncTask<String, Void, Long>
{   
    @Override
    protected Long doInBackground(String... parms)
    {
        long totalsize = 0;
        String filepath = parms[0];
        byte[] fileByte = convertAudioFileToByte(new File(filepath));        

        //Tried base64 below with Convert.FromBase64 on the C# side
        //String bytesstring = Base64.encodeToString(fileByte, Base64.DEFAULT);

        String bytesstring = "";
        try 
        {
            String t = new String(fileByte,"UTF-8");
    bytesstring = t;
        } catch (UnsupportedEncodingException e1)
        {
        // TODO Auto-generated catch block
        e1.printStackTrace();
        }

        URL url;
        HttpURLConnection urlConnection = null;
        try {
            url = new URL("http://my.webservice.com:8185/api/media");

            //setup for connection
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setUseCaches(false);
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setRequestProperty("Content-Type","application/json");
            urlConnection.setRequestProperty("Accept","application/json");
            urlConnection.connect();

            JSONObject json = new JSONObject();
            json.put("AudioSource", bytesstring);
            json.put("ExtraInfo", "none");

            DataOutputStream output = new DataOutputStream(urlConnection.getOutputStream());
            output.writeBytes(URLEncoder.encode(json.toString(),"UTF-8"));
            output.flush();
            output.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            urlConnection.disconnect();
        }
        return totalsize;
    }

    protected void onPreExecute(){

    }
    protected void onPostExecute(){

    }
    private byte[] convertAudioFileToByte(File file) {
        byte[] bFile = new byte[(int) file.length()];

        try {
            // convert file into array of bytes
            FileInputStream fileInputStream = new FileInputStream(file);
            fileInputStream.read(bFile);
            fileInputStream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return bFile;
    }
}

我可以讓 .NET 應用程序使用相同的 API 發送音頻流,但不能使用 Android。 就像我說的,我已經嘗試了許多在互聯網上找到的帶有編碼和輸出流的配置,但仍然得到 500。我需要幫助,因為我不知所措。

提前致謝

我使用了ByteArrayEntity而不是StringEntity

// ByteArrayEntity 

HttpPost request = new HttpPost(getString(R.string.server_url) + "SendMessage");
ByteArrayEntity be = new ByteArrayEntity(msg);
be.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded"));
request.setEntity(be);
HttpResponse response = client.execute(request);

在服務器端,我使用這個 web API 代碼來獲取字節數組:

[HttpPost]
public async Task<string> SendMessage()
{
    byte[] arrBytes = await Request.Content.ReadAsByteArrayAsync();
    return "";
}

我剛剛在使用 AngularJS 和 ASP.NET Web API 上傳/下載字節數組的Stack Overflow 上發布了一個問題,該問題與您的問題相關(部分)。 您可能想閱讀那篇文章來為我的回復設置上下文。 它是關於通過 Web API 發送和接收 byte[] 的。 我對這種方法有一個問題,但它與 JavaScript 客戶端錯誤地處理服務器響應有關。

我將對您的服務器端代碼進行以下更改:

public class PostParms
{
    public string ExtraInfo { get; set; }
}

public class MediaController : ApiController
{
    [HttpPost]// byte[] is sent in body and parms sent in url
    public string Post([FromBody] byte[] audioSource, PostParms parms)
    {
        byte[] bytes = audioSource;
        return "success";
    }
}

閱讀http://byterot.blogspot.com/2012/04/aspnet-web-api-series-part-5.html 上的帖子

為 byte[] 使用/添加 Byte Rot 的異步版本的媒體格式化程序。

對於較新版本的 ASP.NET,我必須調整格式化程序,如下所示。

using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace YOUR_NAMESPACE
{
public class BinaryMediaTypeFormatter : MediaTypeFormatter
{
    /****************** Asynchronous Version ************************/

    private static Type _supportedType = typeof(byte[]);
    private bool _isAsync = true;
    public BinaryMediaTypeFormatter() : this(false){
    }
    public BinaryMediaTypeFormatter(bool isAsync) {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
        IsAsync = isAsync;
    }
    public bool IsAsync {
        get { return _isAsync; }
        set { _isAsync = value; }
    }
    public override bool CanReadType(Type type){
        return type == _supportedType;
    }
    public override bool CanWriteType(Type type){
        return type == _supportedType;
    }
    public override Task<object> ReadFromStreamAsync(Type type, Stream stream,
        HttpContent contentHeaders, IFormatterLogger formatterLogger){// Changed to HttpContent
        Task<object> readTask = GetReadTask(stream);
        if (_isAsync){
            readTask.Start();
        }
        else{
            readTask.RunSynchronously();
        }
        return readTask;
    }
    private Task<object> GetReadTask(Stream stream){
        return new Task<object>(() =>{
            var ms = new MemoryStream();
            stream.CopyTo(ms);
            return ms.ToArray();
        });
    }
    private Task GetWriteTask(Stream stream, byte[] data){
        return new Task(() => {
            var ms = new MemoryStream(data);
            ms.CopyTo(stream);
        });
    }
    public override Task WriteToStreamAsync(Type type, object value, Stream stream,
        HttpContent contentHeaders, TransportContext transportContext){ // Changed to HttpContent
        if (value == null)
            value = new byte[0];
        Task writeTask = GetWriteTask(stream, (byte[])value);
        if (_isAsync){
            writeTask.Start();
        }
        else{
            writeTask.RunSynchronously();
        }
        return writeTask;
    }
}
}

我還必須將以下行添加到配置文件中。

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
     // This line added to activate your binary formatter.
        config.Formatters.Add(new BinaryMediaTypeFormatter());

/************************************* 客戶端代碼 *********** ******************************/

您將需要在客戶端上使用 'Content-Type': 'application/octet-stream'。

您可以將 byte[] 作為二進制發送,但是自從我在客戶端上用 C# 編碼以來已經太久了。

我認為這一行: output.writeBytes(URLEncoder.encode(json.toString(),"UTF-8")); 必須至少更改。

我會看看我是否能找到一些可能相關的 C# 客戶端代碼片段。

編輯您可能會查看以下帖子的 C# 客戶端代碼。 它可以幫助您調整代碼以使用我建議的方法。

如何從 C# 中的 Web Api 方法正確獲取字節數組?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM