javascript - 从 API 响应 JavaScript 播放音频

标签 javascript c# asp.net-mvc

我正在尝试播放下载的音频文件并通过外部 API 在浏览器中播放它。

我有一个本地 API,它正在查询文件所在的外部 API。我从外部 API 获取文件的 API 方法是:

public async Task<HttpResponseMessage> GetAudioAsync(string id)
{
    using (var httpClientHandler = new HttpClientHandler())
    {
        httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
        httpClientHandler.UseDefaultCredentials = true;

        var url = "externalapi/"

        using (var client = new HttpClient(httpClientHandler))
        {
            var result = await client.GetAsync(url);

            var response = new HttpResponseMessage(HttpStatusCode.OK);

            var bytes = await result.Content.ReadAsByteArrayAsync();

            response.Content = new ByteArrayContent(bytes);

            response.Content.Headers.ContentLength = bytes.LongLength;

            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = "audio.wav";
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("audio/wav");

            return response;
        }                    
    }
}

我知道在 Javascript 中我可以设置音频元素的源属性来播放音频。如何从该 API 方法获取数据响应并播放音频?

我尝试了下面的代码,但出现了控制台错误。

$.ajax({
  url: 'api/' + id,
  cache: false,
  type: 'GET'
}).done(function (data) {
  // var blob = new Blob([data], {type: 'audio/wav'});
  // Creating a blob instance removes the error but the audio is not correctly loaded to the audio element. I get no playback.      
  document.getElementById('filename').setAttribute('src', window.URL.createObjectURL(data));
}).fail(function(error) {
  console.log(error);
});

我从浏览器返回的错误是:ERROR TypeError: Failed to construct 'Blob': Iterator getter is not callable.

我从本地 API 得到的响应是:

{
    "version": {
        "major": 1,
        "minor": 1,
        "build": -1,
        "revision": -1,
        "majorRevision": -1,
        "minorRevision": -1
    },
    "content": {
        "headers": [
            {
                "key": "Content-Length",
                "value": [
                    "0"
                ]
            },
            {
                "key": "Content-Disposition",
                "value": [
                    "attachment; filename=audio.wav"
                ]
            },
            {
                "key": "Content-Type",
                "value": [
                    "application/octet-stream"
                ]
            }
        ]
    },
    "statusCode": 200,
    "reasonPhrase": "OK",
    "headers": [],
    "requestMessage": null,
    "isSuccessStatusCode": true
}

更新:

我认为问题可能在于当我使用 console.log(data) 时,我得到的是一个对象而不是一个字节数组。这可用于初始化 Blob 对象。

最佳答案

您可以将 audio 元素的 src 属性设置为直接指向 ASP.NET Web API 端点:

<audio src="http://localhost:8000/api/endpoint/callId"></audio>

如果你需要动态设置它,你可以通过 javascript 来完成:

function setAudioElementSource(id)
{ 
  document.getElementById('yourAudioElement').setAttribute('src', 'http://localhost:8000/api/endpoint/callId')
}

其中 endpoint 是您的 Controller 的名称,callId 是您的调用 ID。

这是我返回调用的操作示例:

[HttpGet]
public async Task<HttpResponseMessage> GetAudioAsync(
    string id)
{
    var url = "http://localhost:8000/api/ExternalApi";

    using (var httpClientHandler = new HttpClientHandler())
    {
        httpClientHandler.UseDefaultCredentials = true;                

        using (var client = new HttpClient(httpClientHandler))
        {
            var result = await client.GetAsync(url);

            var response = new HttpResponseMessage(HttpStatusCode.OK);

            var bytes = await result.Content.ReadAsByteArrayAsync();

            response.Content = new ByteArrayContent(bytes);

            response.Content.Headers.ContentLength = bytes.LongLength;

            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = "audio.wav";
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("audio/wav");

            return response;
        }
    }
}

这是在 Fiddler 中捕获的响应:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: audio/wav
Expires: -1
Server: Microsoft-IIS/10.0
Content-Disposition: attachment; filename=audio.wav
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcdGphYXJ0LnZhbmRlcndhbHRcZG9jdW1lbnRzXHZpc3VhbCBzdHVkaW8gMjAxNVxQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVxkb3dubG9hZFwxMjM=?=
X-Powered-By: ASP.NET
Date: Mon, 20 Aug 2018 09:12:45 GMT
Content-Length: 0

Content-Length 为 0,因为我在 ExternalApi 方法中返回一个空白字节数组,您的 Content-Length header 的值应大于 0。

如果您没有收到任何错误,请尝试使用不同的浏览器,某些浏览器不支持播放 .wav 文件


旁注:

您还可以创建一个继承自 HttpResponseMessage 的自定义类 FileResponse

public class FileResponse
     : HttpResponseMessage
{
    public FileResponse(
          byte[] fileContent
        , string mediaType
        , string fileName)
    {
        StatusCode = System.Net.HttpStatusCode.OK;
        Content = new StreamContent(new MemoryStream(fileContent));
        Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(mediaType);
        Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = fileName };
    }
}

用法:

[HttpGet]
public async Task<HttpResponseMessage> GetAudioAsync(
    string id)
{
    var url = "http://localhost:8000/api/ExternalApi";

    using (var httpClientHandler = new HttpClientHandler())
    {
        httpClientHandler.UseDefaultCredentials = true;                

        using (var client = new HttpClient(httpClientHandler))
        {
            var result = await client.GetAsync(url);                    

            var bytes = await result.Content.ReadAsByteArrayAsync();
            return new FileResponse(bytes, "audio/wav", "your-file-name.wav");
        }
    }
}

关于javascript - 从 API 响应 JavaScript 播放音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51897342/

相关文章:

javascript - jQuery - addClass 到多个项目,当其中一个项目是 var

javascript - 使用 mysql 表进行表单验证

c# - 创建将值作为 Action<T> 实例的字典的语法是什么?

c# - linq - 如何查找一个集合的键列是否是另一个集合的子集?

javascript - 如何在 asp.net 中的页面回发后保持页面滚动位置

asp.net-mvc - HtmlHelper扩展方法与局部 View ?

javascript - 在 jQuery 中禁用下拉列表

javascript - 如何格式化 "if val 1 or 4 or 6 or 10"

javascript - 如何使背景图像在页面打开/刷新时慢慢模糊?

c# - 单独项目中 MVC 解决方案中的 Web API