Reputation: 6605
I'm using ASP.NET MVC and C# for a project.
One task is: when a user clicks on a link, it needs get the id from the link, then use this link to generate an external link, which is a audio file, then play it in web browser (not save as file).
The current solution is: download the audio file from the external link, get the bytes, then put it in the response as audio/wav
public async Task<HttpResponseMessage> StreamAudioAsync(string id)
{
var response = Request.CreateResponse(HttpStatusCode.Moved);
var data = GetAudio(id);
if (data != null && data.Length > 0)
{
response.StatusCode = HttpStatusCode.OK;
response.Content = new ByteArrayContent(data);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("audio/wav");
}
return response;
}
private byte[] GetAudio(string id)
{
string accessKey = Cp.Service.Settings.AccessKey;
string secretAccessKey = Cp.Service.Settings.SecretAccessKey;
string url = string.Format("https://....../......php?access_key={0}&secret_access_key={1}&action=recording.download&format=mp3&sid={2}", accessKey, secretAccessKey, id);
byte[] data = null;
try
{
using (var wc = new System.Net.WebClient())
{
data = wc.DownloadData(url);
}
}
catch //(Exception ex)
{
//forbidden, proxy issues, file not found (404) etc
//ms = null;
}
return data;
}
This will download the audio data first. Is there a way to stream the audio stream from the url directly to the response? so that, the server will not hold the data bytes[]
in memory? Sometimes, the data size is huge.
Thanks
Upvotes: 4
Views: 4558
Reputation: 16596
There are two places in your code where you are working with byte
arrays.
WebClient.DownloadData
returns the entire remote resource as a byte[]
. If you instead used WebClient.OpenRead
(i.e. wc.OpenRead(url);
) you get a Stream
through which to read the remote resource.
Further, you are instantiating a ByteArrayContent
to provide the audio data to your remote client. I see there is also a StreamContent
class with which you can specify a Stream
to send to the remote client.
This is untested and I'm not sure if disposing the WebClient
before response.Content
is consumed will be problematic, or if/how/where the Stream
returned by wc.OpenRead(url)
should be explicitly disposed, but this should give you the idea...
public async Task<HttpResponseMessage> StreamAudioAsync(string id)
{
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.StatusCode = HttpStatusCode.OK;
using (var wc = new System.Net.WebClient())
{
string accessKey = Cp.Service.Settings.AccessKey;
string secretAccessKey = Cp.Service.Settings.SecretAccessKey;
string url = string.Format("https://....../......php?access_key={0}&secret_access_key={1}&action=recording.download&format=mp3&sid={2}", accessKey, secretAccessKey, id);
response.Content = new StreamContent(wc.OpenRead(url));
}
response.Content.Headers.ContentType = new MediaTypeHeaderValue("audio/wav");
return response;
}
Upvotes: 3