I am trying to write a video streaming site using an embedded VLC control to play the video and an asp.net handler to get the video stream. I am embedding the control as follows:
<embed type="application/x-vlc-plugin" pluginspage="http://www.videolan.org" width="640" height="480" target="http://MyWebsite/MyHandler.ashx"/>
<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://download.videolan.org/pub/videolan/vlc/last/win32/axvlc.cab"></object>
And the code i am using in the handler to stream the video is:
public void ProcessRequest(HttpContext context)
{
context.Response.Buffer = false;
context.Response.ContentType = "text/plain";
var path = #"c:/file.avi";
var file = new FileInfo(path);
var len = (int)file.Length;
context.Response.AppendHeader("content-length", len.ToString());
var buffer = new byte[1024];
var outStream = context.Response.OutputStream;
using (Stream stream = File.OpenRead(path))
{
int bytes;
while (len > 0 && (bytes = stream.Read(buffer, 0, buffer.Length)) > 0)
{
outStream.Write(buffer, 0, bytes);
len -= bytes;
}
}
}
While this works and streams the video, I am unable to seek back or forward, the seek bar doesn't move at all. I thought since I sent the file size it would be able to calculate positions but I guess not. Is it possible to seek in the video or will it not be possible since it is a stream (even though it is not a 'true' stream since it is coming from a file with a defined size etc)
Related
I'm using a foreach to insert between video files to play for streaming, however only works for the first video
public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
{
foreach (VideoInfo video in _videos)
{
var buffer = new byte[1024];
bool cancel = false;
int bytes;
int copiedBytes = 0;
using (Stream source = response.GetResponseStream())
{
while (!cancel && (bytes = source.Read(buffer, 0, buffer.Length)) > 0)
{
await outputStream.WriteAsync(buffer, 0, bytes);
}
}
}
}
Since your using is inside the foreach loop, the response stream is closed and disposed after the first video has been sent.
I would suggest to put the using around the foreach. Also, I wonder if the video headers will mess up things, since you keep sending every time again.
I am using the following piece of code to open a PDF file that I have just created this methods works in one section on my site but it does not seem to redirect to the PDF from another section of my site. What could possible be the reason why the PDF file is not opening.
Context.Response.Buffer = false;
FileStream inStr = null;
byte[] buffer = new byte[1024];
long byteCount;
inStr = File.OpenRead(pdfPath);
while ((byteCount = inStr.Read(buffer, 0, buffer.Length)) > 0) {
if (Context.Response.IsClientConnected) {
Context.Response.ContentType = "application/pdf";
Context.Response.OutputStream.Write(buffer, 0, buffer.Length);
Context.Response.Flush();
}
}
Your pdf path is relative.
You could also read the file in one shot
bytez=File.ReadAllBytes(Server.MapPath(pdfPath))
And send it the same way. Response.BinaryWrite(bytez).
I am try to download a zip file via a url to extract files from. I would rather not have to save it a temp file (which works fine) and rather keep it in memory - it is not very big. For example, if I try to download this file:
http://phs.googlecode.com/files/Download%20File%20Test.zip
using this code:
using Ionic.Zip;
...
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.ContentLength > 0)
{
using (MemoryStream zipms = new MemoryStream())
{
int bytesRead;
byte[] buffer = new byte[32768];
using (Stream stream = response.GetResponseStream())
{
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
zipms.Write(buffer, 0, bytesRead);
ZipFile zip = ZipFile.Read(stream); // <--ERROR: "This stream does not support seek operations. "
}
using (ZipFile zip = ZipFile.Read(zipms)) // <--ERROR: "Could not read block - no data! (position 0x00000000) "
using (MemoryStream txtms = new MemoryStream())
{
ZipEntry csentry= zip["Download File Test.cs"];
csentry.Extract(txtms);
txtms.Position = 0;
using (StreamReader reader = new StreamReader(txtms))
{
string csentry = reader.ReadToEnd();
}
}
}
}
...
Note where i flagged the errors I am receiving. With the first one, it does not like the System.Net.ConnectStream. If I comment that line out and allow it to hit the line where I note the second error, it does not like the MemoryStream. I did see this posting: https://stackoverflow.com/a/6377099/1324284 but I am having the same issues that others mention about not having more then 4 overloads of the Read method so I cannot try the WebClient.
However, if I do everything via a FileStream and save it to a temp location first, then point ZipFile.Read at that temp location, everything works including extracting any contained files into a MemoryStream.
Thanks for any help.
You need to Flush() your MemoryStream and set the Position to 0 before you read from it, otherwise you are trying to read from the current position (where there is nothing).
For your code:
ZipFile zip;
using (Stream stream = response.GetResponseStream())
{
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
zipms.Write(buffer, 0, bytesRead);
zipms.Flush();
zipms.Position = 0;
zip = ZipFile.Read(zipms);
}
(Warning: First time on Stackoverflow) I want to be able to read in a pdf via binary but I encounter an issue when writing it back to the isolated storage. When it is written back to isolated storage and I try to open the file but I get an error message from adobe reader saying this is not a valid pdf. The file is 102 Kbytes but when I write it to isolated storage it is 108 Kbytes.
My reasoning for doing this is that I want to be able to split the pdfs. I have tried PDFsharp (doesn't open all pdf types). Here is my code:
public void pdf_split()
{
string prefix = #"/PDFread;component/";
string fn = originalFile;
StreamResourceInfo sr = Application.GetResourceStream(new Uri(prefix + fn, UriKind.Relative));
IsolatedStorageFile iStorage = IsolatedStorageFile.GetUserStoreForApplication();
using (var outputStream = iStorage.OpenFile(sFile, FileMode.CreateNew))
{
Stream resourceStream = sr.Stream;
long length = resourceStream.Length;
byte[] buffer = new byte[32];
int readCount = 0;
while (readCount < length)
{
int read = sr.Stream.Read(buffer, 0, buffer.Length);
readCount += read;
outputStream.Write(buffer, 0, read);
}
}
}
I have the following code which downloads video content:
WebRequest wreq = (HttpWebRequest)WebRequest.Create(url);
using (HttpWebResponse wresp = (HttpWebResponse)wreq.GetResponse())
using (Stream mystream = wresp.GetResponseStream())
{
using (BinaryReader reader = new BinaryReader(mystream))
{
int length = Convert.ToInt32(wresp.ContentLength);
byte[] buffer = new byte[length];
buffer = reader.ReadBytes(length);
Response.Clear();
Response.Buffer = false;
Response.ContentType = "video/mp4";
//Response.BinaryWrite(buffer);
Response.OutputStream.Write(buffer, 0, buffer.Length);
Response.End();
}
}
But the problem is that the whole file downloads before being played. How can I make it stream and play as it's still downloading? Or is this up to the client/receiver application to manage?
You're reading the entire file into a single buffer, then sending the entire byte array at once.
You should read into a smaller buffer in a while loop.
For example:
byte[] buffer = new byte[4096];
while(true) {
int bytesRead = myStream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
Response.OutputStream.Write(buffer, 0, bytesRead);
}
This is more efficient for you especially if you need to stream a video from a file on your server or even this file is hosted at another server
File On your server:
context.Response.BinaryWrite(File.ReadAllBytes(HTTPContext.Current.Server.MapPath(_video.Location)));
File on external server:
var wc = new WebClient();
context.Response.BinaryWrite(wc.DownloadData(new Uri("http://mysite/video.mp4")));
Have you looked at Smooth Streaming?
Look at sample code here