【问题标题】:Posting Audio (byte array) to MVC.NET Web Api将音频(字节数组)发布到 MVC.NET Web Api
【发布时间】:2014-02-12 04:10:34
【问题描述】:

问题

我正在尝试将我的 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。我需要帮助,因为我不知所措。

提前致谢

【问题讨论】:

    标签: c# android asp.net-mvc audio asp.net-web-api


    【解决方案1】:

    我使用了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 "";
    }
    

    【讨论】:

    • 为我工作谢谢!!
    【解决方案2】:

    我刚刚在 Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API 上发布了一个与您的问题相关(部分)的问题。您可能想阅读该帖子以设置我的回复的上下文。它是关于通过 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 的异步版本的 Media Formatter。

    我不得不为更新版本的 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# 客户端代码 sn-ps。

    编辑您可能会查看以下帖子的 C# 客户端代码。它可以帮助您调整代码以使用我建议的方法。

    How to Get byte array properly from an Web Api Method in C#?

    【讨论】:

      猜你喜欢
      • 2015-11-17
      • 2012-04-28
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      相关资源
      最近更新 更多