我正在尝试播放下载的音频文件,然后从外部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中,我可以将音频元素的source属性设置为播放音频。如何从此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);
});


我从浏览器返回的错误是:错误TypeError:无法构造“ Blob”:迭代器getter不可调用。

我从本地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标头的值应大于0。

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



边注:

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

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");
        }
    }
}

10-01 04:30
查看更多