I tried to write a text file using OutputStream.Write but, I've noticed that the last character of the file is not being sent.
Whether the file is 6KB or 242KB, the last character is skipped.
AwAIB0UfFlJTSTNABEQWGgMVAhNFBkVeKgVTSx4LCVQMBUUQRUMwBVFTGwcAEAASRRNTBipNQQMFDREYB
BUAH0VIKgVLRVccCRFFGRcbR08wREgDEQENEUkCDRNOTX5cS1ZXHgQGHFYIB0NOfgUIAwMABFQABBcdUg
YpRFcDHgZBAA0TRTEDBj1KQEZXREEdRRIKHFQGK0tARgUbFRULEkUFSF9+R1FXVxwJEUUkAAFQSTBWQQ0
xBBQHDV5MUkFIOgV2RgQYDhoWE0sxTEktQAwKVx8AB0UCDRcAQyxXS1FZSBUcBAIWUldDN1dAAxEHE1QI
E0UTTkJ+TARAFgYVVBAYARdSVSpESkdXAAAcBFg=
Note: whole text is one line in the text file.
My text file is somewhat similar to the above. So can anyone help me out?
My code:
var path = Request.QueryString["path"];
path = Server.MapPath(Url.Content("~/Files/" + path + "/somefile.txt"));
Response.Buffer = false;
Response.ContentType = "text/plain";
FileInfo file = new FileInfo(path);
int len = (int)file.Length, bytes;
Response.AppendHeader("content-length", len.ToString());
byte[] buffer = new byte[1024];
Stream outStream = Response.OutputStream;
using (Stream stream = System.IO.File.OpenRead(path))
{
while (len > 0 && (bytes = stream.Read(buffer, 0, buffer.Length)) > 0)
{
outStream.Write(buffer, 0, bytes);
len -= bytes;
}
}
Response.Flush();
Response.Close();
UPDATE 1:
Now shows the complete text from the file.
UPDATE 2 :
Updated the complete C# code.
UPDATE 3:
Thanks, my friends, for all your efforts! I somehow made it work - the problem was Response.Flush() and Response.Close(); once I removed these 2 statements it started working. I don't understand why this problem occurred as I always use Response.Flush() and Response.Close(). I never received this kind of error but this was the first time. If anyone could give me an explanation, it would be appreciated. I will mark #AlexeiLevenkov's post as the answer, as I just tested it again without the Response.Flush and Close() and it is working.
Stream.CopyTo is easier approaach (as long as you can use .Net 4.0).
using (var stream = System.IO.File.OpenRead(path))
{
stream.CopyTo(outStream);
}
I think you need to call Response.Flush() or outStream.Flush()
Related
I need to redirect an audio stream to avoid CORS in order to use AudioContext() for visualizations.
Instead of using the original stream url, I'd point the player to "mysite.com/stream/", which would intercept the stream and feed it to the player.
I really don't know what I'm doing in this case, which should be obvious from my attempt below. Thanks to anyone for some help.
System.Net.HttpWebRequest web = (System.Net.HttpWebRequest)System.Net.WebRequest.Create("https://ssl.geckohost.nz/proxy/caitlinssl?mp=/stream");
Response.ContentType = "audio/aac";
char[] buffer = new char[8192];
byte[] buffer_bytes = new byte[8192];
using (System.Net.HttpWebResponse web_resp = (System.Net.HttpWebResponse)web.GetResponse())
{
using (System.IO.Stream stream_web = web_resp.GetResponseStream())
{
//stream_web.CopyTo(Response.OutputStream);
using (System.IO.StreamReader stream_rdr = new System.IO.StreamReader(stream_web))
{
for (var i = 0; i < 100; i++)
{
stream_rdr.Read(buffer, 0, 8192);
Response.Write(buffer);
Response.Flush();
}
}
}
}
The solution I found was originally created for use with NAudio to play a remote MP3 file, but I was able to repurpose it for my needs. There are probably better ways, but this works.
Play audio from a stream using C#
Edit: It seems that the connection is dropped server to server, but I'm not positive. IIS will not send "Connection: keep-alive" to the client, however it is being sent to the client by the original stream. Tried adding KeepAlive = true to the WebRequest, and changing the protocol version to HTTP 1.0 to keep the server to server connection alive with no joy.
string url = "https://ssl.geckohost.nz/proxy/caitlinssl?mp=/stream";
Response.ContentType = "audio/aac";
using (Stream stream = WebRequest.Create(url).GetResponse().GetResponseStream())
{
byte[] buffer = new byte[32768];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
Response.OutputStream.Write(buffer, 0, read);
Response.Flush();
}
}
Conclusion: It seems that in this case it is not possible with IIS to persist the connection server to server, as far as I was able to find. I'm not worried about scalability as this is a personal project for a user of 1. The solution I ended up with is to start capturing the stream with ffmpeg on click, transcode it to flac/mkv, and use a variation of the above to read the file while it's being written and feed it to the player (WPF WebView [IE/Edge]).
currently i'm facing issue while creating file, i'm trying to write text contents using streamWriter class but i'm not getting expected answer..
Below is my example code :-
My c# code looks like :-
public void ProcessRequest(HttpContext context)
{
// Create a connexion to the Remote Server to redirect all requests
RemoteServer server = new RemoteServer(context);
// Create a request with same data in navigator request
HttpWebRequest request = server.GetRequest();
// Send the request to the remote server and return the response
HttpWebResponse response = server.GetResponse(request);
context.Response.AddHeader("Content-Disposition", "attachment; filename=playlist.m3u8");
context.Response.ContentType = response.ContentType;
Stream receiveStream = response.GetResponseStream();
var buff = new byte[1024];
int bytes = 0;
string token = Guid.NewGuid().ToString();
while ((bytes = receiveStream.Read(buff, 0, 1024)) > 0)
{
//Write the stream directly to the client
context.Response.OutputStream.Write(buff, 0, bytes);
context.Response.Write("&token="+token);
}
//close streams
response.Close();
context.Response.End();
}
output of above code looks like :-
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=20776,CODECS="avc1.66.41",RESOLUTION=320x240
chunk.m3u8?nimblesessionid=62
&token=42712adc-f932-43c7-b282-69cf349941da
But my expected output is :-
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=20776,CODECS="avc1.66.41",RESOLUTION=320x240
chunk.m3u8?nimblesessionid=62&token=42712adc-f932-43c7-b282-69cf349941da
I just wanted that token param in same line instead of new line..
Thank you.
If you want to simply remove a newline at the end of the received bytes, change the code in your while loop like so:
while ((bytes = receiveStream.Read(buff, 0, 1024)) > 0)
{
if (buff[bytes-1] == 0x0a)
bytes -= 1;
//Write the stream directly to the client
context.Response.OutputStream.Write(buff, 0, bytes);
context.Response.Write("&token="+token);
}
Several caveats:
It will only work if 0x0a (newline byte, '\n' as a character) is at the end of the bytes you received. If for some reason the message sent by the server is received in several blocks, you will first have to make sure you received everything there is to receive before checking the last byte.
Please also note that this would result in multiple &token=... lines in your current code.
Depending on the server, it might use carriage return (0x0d or '\r') as its line ending byte, or even both. Check what the server sends and adapt the code accordingly.
I have to serve large files (200-800MB) to the client from my controller. I tested FileStreamResult, but this class buffered the whole file in memory. This behavior is not good enough for my project.
Further i testest the approach from here: http://support.microsoft.com/kb/812406. Concerning the memory, this looks pretty good -but the files are not completly downloaded on the client (the original file is 210222 KB, the downloaded ones are 209551 to 209776). This means there is about 0.5 MB lost (which concequently causes the files to be broken).
Has somebody an idea? Whats the best way to do this anyway? Im grateful for everything.
Just for users in the future, the link pointed to the following code:
System.IO.Stream iStream = null;
// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file to download including its path.
string filepath = "DownloadFileName";
// Identify the file name.
string filename = System.IO.Path.GetFileName(filepath);
try
{
// Open the file.
iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
System.IO.FileAccess.Read,System.IO.FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
Response.Flush();
buffer= new Byte[10000];
dataToRead = dataToRead - length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
Response.Write("Error : " + ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
Response.Close();
}
Update
This is my action:
public DownloadResult TransferTest()
{
string fullFilePath = #"C:\ws\Test\Test\Templates\example.pdf";
return new DownloadResult(fullFilePath);
}
I simply call the action directly from my browser (http://xxx.xxx/Other/TransferTest).
The code basically looks sound - you are more-or-less correctly handling the return value from Read (if I was being picky, I would say check it for <=0, but this would not be an expected behavior since you probably have a lock on the file).
The only thing that occurs is: try adding a:
Response.OutputStream.Flush();
and perhaps:
Response.OutputStream.Close();
to make sure that the output stream is flushed.
I´m trying to play wav files with the audio element. This works great when I reference the file directly BUT when I try to stream it via a c# FileStream it stops working.
The code below work perfect for Chrome and Opera on PC but I am trying to get it to work on Ipad and Firefox.
I am using .net framwork 2.0
I have to use wav.
<audio id="audio" src="www.acme.com/streamer.aspx?music=test.wav" controls preload="auto"></audio> Not working
<audio id="audio" src="test.wav" controls preload="auto"></audio> Working
The stream function below:
string wavFileName = test.wav;
FileStream soundStream;
long FileSize;
soundStream = new FileStream(#"\\netshare\" + wavfileName, FileMode.Open, FileAccess.Read, FileShare.Read, 256);
FileSize = soundStream.Length;
byte[] Buffer = new byte[(int)FileSize];
int count = 0;
int offset = 0;
while ((count = soundStream.Read(Buffer, offset,
Buffer.Length)) > 0)
{
Response.OutputStream.Write(Buffer, offset, count);
}
Response.Buffer = true;
Response.Clear();
Response.AddHeader("Content-Type", "audio/wave");
Response.AddHeader("Content-Disposition", "attachment;filename=" + wavfileName);
Response.ContentType = "audio/wave";
Response.BinaryWrite(Buffer);
if (soundStream != null)
{
soundStream.Close();
}
Response.End();
(btw, this is my first post, hope i did not break any rules)
The code seems fine. I think you need to make sure that the wav file is in the write PCM format. Some browsers have issues playing certain PCMs. I found out that just because a browse(html5)) supports a wav file does not mean it will actually play all wav type.
You might also want to flush the Response.
I'm reading data (an adCenter report, as it happens), which is supposed to be zipped. Reading the contents with an ordinary stream, I get a couple thousand bytes of gibberish, so this seems reasonable. So I feed the stream to DeflateStream.
First, it reports "Block length does not match with its complement." A brief search suggests that there is a two-byte prefix, and indeed if I call ReadByte() twice before opening DeflateStream, the exception goes away.
However, DeflateStream now returns nothing at all. I've spent most of the afternoon chasing leads on this, with no luck. Help me, StackOverflow, you're my only hope! Can anyone tell me what I'm missing?
Here's the code. Naturally I only enabled one of the two commented blocks at a time when testing.
_results = new List<string[]>();
using (Stream compressed = response.GetResponseStream())
{
// Skip the zlib prefix, which conflicts with the deflate specification
compressed.ReadByte(); compressed.ReadByte();
// Reports reading 3,000-odd bytes, followed by random characters
/*byte[] buffer = new byte[4096];
int bytesRead = compressed.Read(buffer, 0, 4096);
Console.WriteLine("Read {0} bytes.", bytesRead.ToString("#,##0"));
string content = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine(content);*/
using (DeflateStream decompressed = new DeflateStream(compressed, CompressionMode.Decompress))
{
// Reports reading 0 bytes, and no output
/*byte[] buffer = new byte[4096];
int bytesRead = decompressed.Read(buffer, 0, 4096);
Console.WriteLine("Read {0} bytes.", bytesRead.ToString("#,##0"));
string content = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine(content);*/
using (StreamReader reader = new StreamReader(decompressed))
while (reader.EndOfStream == false)
_results.Add(reader.ReadLine().Split('\t'));
}
}
As you can probably guess from the last line, the unzipped content should be TDT.
Just for fun, I tried decompressing with GZipStream, but it reports that the magic number is not correct. MS' docs just say "The downloaded report is compressed by using zip compression. You must unzip the report before you can use its contents."
Here's the code that finally worked. I had to save the content out to a file and read it back in. This does not seem reasonable, but for the small quantities of data I'm working with, it's acceptable, I'll take it!
WebRequest request = HttpWebRequest.Create(reportURL);
WebResponse response = request.GetResponse();
_results = new List<string[]>();
using (Stream compressed = response.GetResponseStream())
{
// Save the content to a temporary location
string zipFilePath = #"\\Server\Folder\adCenter\Temp.zip";
using (StreamWriter file = new StreamWriter(zipFilePath))
{
compressed.CopyTo(file.BaseStream);
file.Flush();
}
// Get the first file from the temporary zip
ZipFile zipFile = ZipFile.Read(zipFilePath);
if (zipFile.Entries.Count > 1) throw new ApplicationException("Found " + zipFile.Entries.Count.ToString("#,##0") + " entries in the report; expected 1.");
ZipEntry report = zipFile[0];
// Extract the data
using (MemoryStream decompressed = new MemoryStream())
{
report.Extract(decompressed);
decompressed.Position = 0; // Note that the stream does NOT start at the beginning
using (StreamReader reader = new StreamReader(decompressed))
while (reader.EndOfStream == false)
_results.Add(reader.ReadLine().Split('\t'));
}
}
You will find that DeflateStream is hugely limited in what data it will decompress. In fact if you are expecting entire files it will be of no use at all.
There are hundereds of (mostly small) variations of ZIP files and DeflateStream will get along only with two or three of them.
Best way is likely to use a dedicated library for reading Zip files/streams like DotNetZip or SharpZipLib (somewhat unmaintained).
You could write the stream to a file and try my tool Precomp on it. If you use it like this:
precomp -c- -v [name of input file]
any ZIP/gZip stream(s) inside the file will be detected and some verbose information will be reported (position and length of the stream). Additionally, if they can be decompressed and recompressed bit-to-bit identical, the output file will contain the decompressed stream(s).
Precomp detects ZIP/gZip (and some other) streams anywhere in the file, so you won't have to worry about header bytes or garbage at the beginning of the file.
If it doesn't detect a stream like this, try to add -slow, which detects deflate streams even if they don't have a ZIP/gZip header. If this fails, you can try -brute which even detects deflate streams that lack the two byte header, but this will be extremely slow and can cause false positives.
After that, you'll know if there is a (valid) deflate stream in the file and if so, the additional information should help you to decompress other reports correctly using zLib decompression routines or similar.