Html5 Audio - Refresh Page not work to reset audio - asp.net-mvc

Hi I need help from you - ASP.NET MVC.
In my web application, I have a html5 audio.
It works once, but when you refresh the page, this video is in the browser's memory.
When I refresh the page, it should hit new controller action, just like the first time.
Please look at my code below:
My View
<audio controls style="width: 400px;">
<source src="#Url.Action("StreamUploadedSong")" type="audio/mp3" />
Your browser does not support the audio element.
</audio>
My Controller
public FileStreamResult StreamUploadedSong() // <--------- Do not enter here the second time.
{
byte[] teste = null;
string query1 = "SELECT * FROM Video WHERE Id= '2'";
using (SqlConnection connection1 = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
using (SqlCommand command1 = new SqlCommand(query1, connection1))
{
connection1.Open();
var reader = command1.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
teste = (byte[])reader["Voice"];
}
connection1.Close();
}
long fSize = teste.Length;
long startbyte = 0;
long endbyte = fSize - 1;
int statusCode = 200;
if ((Request.Headers["Range"] != null))
{
//Get the actual byte range from the range header string, and set the starting byte.
string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
startbyte = Convert.ToInt64(range[1]);
if (range.Length > 2 && range[2] != "") endbyte = Convert.ToInt64(range[2]);
//If the start byte is not equal to zero, that means the user is requesting partial content.
if (startbyte != 0 || endbyte != fSize - 1 || range.Length > 2 && range[2] == "")
{ statusCode = 206; }//Set the status code of the response to 206 (Partial Content) and add a content range header.
}
long desSize = endbyte - startbyte + 1;
//Headers
Response.StatusCode = statusCode;
Response.ContentType = "audio/mp3";
Response.AddHeader("Content-Accept", Response.ContentType);
Response.AddHeader("Content-Length", desSize.ToString());
Response.AddHeader("Content-Range", string.Format("bytes {0}-{1}/{2}", startbyte, endbyte, fSize));
//Data
var stream = new MemoryStream(teste, (int)startbyte, (int)desSize);
return new FileStreamResult(stream, Response.ContentType);
}
Any idea how to refresh page to enter controller action StreamUploadedSong again?

I found solution !
Using Guid.NewGuid to Initializes a new instance of the Guid structure.
Bruce commented on this forum The Asp.net MVC:
"The browser caches the audio. If you want it to fetch every time, the URL should be unique. Just add a guid to the URL."
Source: ASP.NET Forums
Replace:
<source src="#Url.Action("StreamUploadedSong")" type="audio/mp3" />
to
<source src="#Url.Action("StreamUploadedSong", "Account", new {id = Guid.NewGuid()})" type="audio/mp3" />

Related

MVC audio controls playing song from bytes

I have my songs stored in database as bytes[]. How do I use these in the <audio> tag.
So something like this. Do I need to convert the bytes to something else first? I am not sure.
foreach (var item in Model)
{
<audio controls>
<source src=#item.SongBytes type="audio/mp3"/>
</audio>
}
One way would be to add a new action in your controller that returns the data:
public ActionResult Audio(int someId)
{
byte[] songBytes;
// Add code to get data
return new FileStreamResult(songBytes, "audio/mp3");
}
Then put the URL to that into the src attribute:
foreach (var item in Model)
{
<audio controls>
<source src="/Controller/Audio/#item.someId" type="audio/mp3"/>
</audio>
}
Google chrome/Ipad require support for content-range requests, so to add to given answer here, do something like this:
public FileStreamResult StreamUploadedSongs(int id)
{
byte[] song = db.UploadedSongs.Where(x => x.Id == id).FirstOrDefault().SongBytes;
long fSize = song.Length;
long startbyte = 0;
long endbyte = fSize - 1;
int statusCode = 200;
if ((Request.Headers["Range"] != null))
{
//Get the actual byte range from the range header string, and set the starting byte.
string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
startbyte = Convert.ToInt64(range[1]);
if (range.Length > 2 && range[2] != "") endbyte = Convert.ToInt64(range[2]);
//If the start byte is not equal to zero, that means the user is requesting partial content.
if (startbyte != 0 || endbyte != fSize - 1 || range.Length > 2 && range[2] == "")
{ statusCode = 206; }//Set the status code of the response to 206 (Partial Content) and add a content range header.
}
long desSize = endbyte - startbyte + 1;
//Headers
Response.StatusCode = statusCode;
Response.ContentType = "audio/mp3";
Response.AddHeader("Content-Accept", Response.ContentType);
Response.AddHeader("Content-Length", desSize.ToString());
Response.AddHeader("Content-Range", string.Format("bytes {0}-{1}/{2}", startbyte, endbyte, fSize));
//Data
var stream = new MemoryStream(song, (int)startbyte, (int)desSize);
return new FileStreamResult(stream, Response.ContentType);
}
It works for me, my issue is when I tried to play the .wav file via wavesurfer.js in chrome by calling controller method which return the ActionResult then file is playing but I was not able to seek, forward and backward. When I do seek, player returns to start position. Although this functionality is working fine in Firfox.

how to screen scrape and put valid href link that will go to that link

I have scraped a webpage but I want the link to have valid link and will jump to that linkpage when clicked.
ex scraped data: day 1 - Go to my Page - status
I want the Go to my page to jump to whatever link is in its href.
ex. actual html I got
<td>Go to my Page</td>
I need it to be like this:
<td>Go to my Page</td>
here's my code for scraping:
public string ScreenScrape()
{
string url = "http://somewebsite.com/tab/form/index.php";
string strResult = "";
WebResponse objResponse;
WebRequest objRequest = System.Net.HttpWebRequest.Create(url);
objResponse = objRequest.GetResponse();
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
strResult = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
var webGet = new HtmlAgilityPack.HtmlWeb();
var doc = webGet.Load(url);
foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//a[#href]"))
{
HtmlAttribute att = link.Attributes["href"];
att.Value = "http://somewebsite.com/tab/form/"+att.Value;
}
return strResult;
}
Here's my attempt to change the link and remove the javascript string but could not figure out how to get to the right index . Also, once I am able to change that, how do I replace each href in the strResult(above) to the new href?
foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//a[#href]"))
{
HtmlAttribute att = link.Attributes["href"];
att.Value = "http://somewebsite.com/tab/form/" + ....
}
Can anyone pls help me? thanks
nevermind I got it, but I know the html url parsing is not the best way (if you have suggestion on how to parse it better, pls do so). right now, the only goal is to change the href link so here it goes.
public string ScreenScrape()
{
string url = "http://somewebsite.com/tab/form/index.php";
string strResult = "";
WebResponse objResponse;
WebRequest objRequest = System.Net.HttpWebRequest.Create(url);
objResponse = objRequest.GetResponse();
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
strResult = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
var webGet = new HtmlAgilityPack.HtmlWeb();
var doc = webGet.Load(url);
foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//a[#href]"))
{
string removeString ="javascript:jsFormAuth('";
string removeEnd = "');";
HtmlAttribute att = link.Attributes["href"];
String strUrl = HttpContext.Current.Request.Url.AbsoluteUri.Replace(att.XPath, "(");
string sub1 = att.Value.Replace(removeString,"");
string sub2 = sub1.Replace(removeEnd,"");
att.Value = "http://somewebsite.com/tab/form/" + sub2;
}
return doc.DocumentNode.InnerHtml;
}

Downloading Azure Blob files in MVC3

Our ASP.NET MVC 3 application is running on Azure and using Blob as file storage. I have the upload part figured out.
The View is going to have the File Name, which, when clicked will prompt the file download screen to appear.
Can anyone tell me how to go about doing this?
Two options really... the first is to just redirect the user to the blob directly (if the blobs are in a public container). That would look a bit like:
return Redirect(container.GetBlobReference(name).Uri.AbsoluteUri);
If the blob is in a private container, you could either use a Shared Access Signature and do redirection like the previous example, or you could read the blob in your controller action and push it down to the client as a download:
Response.AddHeader("Content-Disposition", "attachment; filename=" + name); // force download
container.GetBlobReference(name).DownloadToStream(Response.OutputStream);
return new EmptyResult();
Here's a resumable version (useful for large files or allowing seek in video or audio playback) of private blob access:
public class AzureBlobStream : ActionResult
{
private string filename, containerName;
public AzureBlobStream(string containerName, string filename)
{
this.containerName = containerName;
this.filename = filename;
this.contentType = contentType;
}
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
var request = context.HttpContext.Request;
var connectionString = ConfigurationManager.ConnectionStrings["Storage"].ConnectionString;
var account = CloudStorageAccount.Parse(connectionString);
var client = account.CreateCloudBlobClient();
var container = client.GetContainerReference(containerName);
var blob = container.GetBlockBlobReference(filename);
blob.FetchAttributes();
var fileLength = blob.Properties.Length;
var fileExists = fileLength > 0;
var etag = blob.Properties.ETag;
var responseLength = fileLength;
var buffer = new byte[4096];
var startIndex = 0;
//if the "If-Match" exists and is different to etag (or is equal to any "*" with no resource) then return 412 precondition failed
if (request.Headers["If-Match"] == "*" && !fileExists ||
request.Headers["If-Match"] != null && request.Headers["If-Match"] != "*" && request.Headers["If-Match"] != etag)
{
response.StatusCode = (int)HttpStatusCode.PreconditionFailed;
return;
}
if (!fileExists)
{
response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
if (request.Headers["If-None-Match"] == etag)
{
response.StatusCode = (int)HttpStatusCode.NotModified;
return;
}
if (request.Headers["Range"] != null && (request.Headers["If-Range"] == null || request.Headers["IF-Range"] == etag))
{
var match = Regex.Match(request.Headers["Range"], #"bytes=(\d*)-(\d*)");
startIndex = Util.Parse<int>(match.Groups[1].Value);
responseLength = (Util.Parse<int?>(match.Groups[2].Value) + 1 ?? fileLength) - startIndex;
response.StatusCode = (int)HttpStatusCode.PartialContent;
response.Headers["Content-Range"] = "bytes " + startIndex + "-" + (startIndex + responseLength - 1) + "/" + fileLength;
}
response.Headers["Accept-Ranges"] = "bytes";
response.Headers["Content-Length"] = responseLength.ToString();
response.Cache.SetCacheability(HttpCacheability.Public); //required for etag output
response.Cache.SetETag(etag); //required for IE9 resumable downloads
response.ContentType = blob.Properties.ContentType;
blob.DownloadRangeToStream(response.OutputStream, startIndex, responseLength);
}
}
Example:
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename); // force download
return new AzureBlobStream(blobContainerName, filename);
I noticed that writing to the response stream from the action method messes up the HTTP headers. Some expected headers are missing and others are not set correctly.
So instead of writing to the response stream, I get the blob content as a stream and pass it to the Controller.File() method.
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
Stream blobStream = blob.OpenRead();
return File(blobStream, blob.Properties.ContentType, "FileName.txt");

PrettyPhoto annd youtube videos overlay

I have a webpage with prettyPhoto and a youtube video inside the web page.
With jquery I do:
$("#youtubevideo embed").attr("wmode", "opaque");
also tried $("#youtubevideo embed").attr("wmode", "transparent");
In firefox image is over the youtube video, but the corners of pretty photo are missing. Not really missing because if I scroll up ad down they are shown. But still they don't appear correctly.
In Chrome video is still on top of the images :( Is there a way to fix this? Thanks
after 2 days of searching the web for the answer i've found a pure JS function that fix it in all browsers!
there you go:
function fix_flash() {
// loop through every embed tag on the site
var embeds = document.getElementsByTagName('embed');
for (i = 0; i < embeds.length; i++) {
embed = embeds[i];
var new_embed;
// everything but Firefox & Konqueror
if (embed.outerHTML) {
var html = embed.outerHTML;
// replace an existing wmode parameter
if (html.match(/wmode\s*=\s*('|")[a-zA-Z]+('|")/i))
new_embed = html.replace(/wmode\s*=\s*('|")window('|")/i, "wmode='transparent'");
// add a new wmode parameter
else
new_embed = html.replace(/<embed\s/i, "<embed wmode='transparent' ");
// replace the old embed object with the fixed version
embed.insertAdjacentHTML('beforeBegin', new_embed);
embed.parentNode.removeChild(embed);
} else {
// cloneNode is buggy in some versions of Safari & Opera, but works fine in FF
new_embed = embed.cloneNode(true);
if (!new_embed.getAttribute('wmode') || new_embed.getAttribute('wmode').toLowerCase() == 'window')
new_embed.setAttribute('wmode', 'transparent');
embed.parentNode.replaceChild(new_embed, embed);
}
}
// loop through every object tag on the site
var objects = document.getElementsByTagName('object');
for (i = 0; i < objects.length; i++) {
object = objects[i];
var new_object;
// object is an IE specific tag so we can use outerHTML here
if (object.outerHTML) {
var html = object.outerHTML;
// replace an existing wmode parameter
if (html.match(/<param\s+name\s*=\s*('|")wmode('|")\s+value\s*=\s*('|")[a-zA-Z]+('|")\s*\/?\>/i))
new_object = html.replace(/<param\s+name\s*=\s*('|")wmode('|")\s+value\s*=\s*('|")window('|")\s*\/?\>/i, "<param name='wmode' value='transparent' />");
// add a new wmode parameter
else
new_object = html.replace(/<\/object\>/i, "<param name='wmode' value='transparent' />\n</object>");
// loop through each of the param tags
var children = object.childNodes;
for (j = 0; j < children.length; j++) {
try {
if (children[j] != null) {
var theName = children[j].getAttribute('name');
if (theName != null && theName.match(/flashvars/i)) {
new_object = new_object.replace(/<param\s+name\s*=\s*('|")flashvars('|")\s+value\s*=\s*('|")[^'"]*('|")\s*\/?\>/i, "<param name='flashvars' value='" + children[j].getAttribute('value') + "' />");
}
}
}
catch (err) {
}
}
// replace the old embed object with the fixed versiony
object.insertAdjacentHTML('beforeBegin', new_object);
object.parentNode.removeChild(object);
}
}
}
now you can just run in when the page loads with jQuery:
$(document).ready(function () {
fix_flash();
}
Also you can add ?wmode=transparent to each youtube link
So if you have code like:
<iframe src="http://www.youtube.com/embed/aoZbiS20HGI">
</iframe>
You need to change it to:
<iframe src="http://www.youtube.com/embed/aoZbiS20HGI?wmode=transparent">
</iframe>

Data missing in ASP post to MVC

I have an ASP page:
<%
sData = "VARIABLE=SOMEDATAHERE"
oHttpRequest.Open "POST", "http://????/AAA/BBB", False
oHttpRequest.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
oHttpRequest.Send sData
oPostResponse = oHttpRequest.ResponseText
Response.Write oPostResponse
%>
I am posting this to an MVC site:
[HttpPost]
public ActionResult BBB(string PORTAL)
{
}
In my BBB function I am unable to get to SOMEDATAHERE.
I have tried:
Request.Form["VARIABLE"]
Request.ServerVariables["VARIABLE"]
Ive tried reading the raw stream using the code below but thats blank too..
I am not sure what else I can try?
System.IO.Stream str; String strmContents;
Int32 counter, strLen, strRead;
// Create a Stream object.
str = Request.InputStream;
// Find number of bytes in stream.
strLen = Convert.ToInt32(str.Length);
// Create a byte array.
byte[] strArr = new byte[strLen];
// Read stream into byte array.
strRead = str.Read(strArr, 0, strLen);
// Convert byte array to a text string.
strmContents = "";
for (counter = 0; counter < strLen; counter++)
{
strmContents = strmContents + strArr[counter].ToString();
}

Resources