I am using c# .net compact framework 3.5 and I want to convert a video file to byte array so that I may upload it on the server.
In the similar manner I am doing the image uploading which is getting the success result.
HttpWebRequest request;
request.ContentType = "image/jpeg";
request.ContentLength = byteArray.Length;
request.Method = "PUT";
imageToByteArray(img).CopyTo(byteArray, 0);
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(byteArray, 0, (int)Fs.Length);
requestStream.Flush();
requestStream.Close();
}
public byte[] imageToByteArray(Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
How to do this for the video files?
You should copy the stream one block at a time instead of reading the entire file into an array. Otherwise, you'll use a potentially very large amount of memory as video files can grow quite big.
For example:
HttpWebRequest request;
request.Method = "PUT";
using(Stream requestStream = request.GetRequestStream())
using(Stream video = File.OpenRead("Path")) {
byte[] buffer = new byte[4096];
while(true) {
int bytesRead = video.Read(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
requestStream.Write(buffer, 0, bytesRead);
}
}
Related
I am trying to write inside http request stream a huge byte array
this is my code:
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytes = encoding.GetBytes(body);
request.ContentType = contentType;
request.ContentLength = bytes.Length;
Stream stream = request.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);
stream.Close();
It works fine with small files but when I try ti write byte array [9264619]I am getting an abort error.
Any suggestions?
I am using the following code to upload a image to my FTP server but I have a problem. If I use the code to check the dimension (height and width) of the image before upload then there is .png file created in the FTP server but it's empty (or invalid format) and if I remove the code to check the dimension, then the image is uploaded correctly. Does any have any idea on this?
public ActionResult UploadFile(int type, HttpPostedFileBase imagefile)
{
//check image height and width
using (System.Drawing.Image image = System.Drawing.Image.FromStream(imagefile.InputStream, true, true))
{
if (image.Width > 160 || image.Height > 160)
{
//do something here
}
}//end check image height and width
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftpPath" + "/" + imagefile.FileName);
request.Credentials = new NetworkCredential("ftpUserName", "ftpPassword");
request.Method = WebRequestMethods.Ftp.UploadFile;
var sourceStream = imagefile.InputStream;
Stream requestStream = request.GetRequestStream();
request.ContentLength = sourceStream.Length;
int BUFFER_SIZE = imagefile.ContentLength;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = sourceStream.Read(buffer, 0, BUFFER_SIZE);
do
{
requestStream.Write(buffer, 0, bytesRead);
bytesRead = sourceStream.Read(buffer, 0, BUFFER_SIZE);
} while (bytesRead > 0);
sourceStream.Close();
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
}
As mentioned, you are reading up all the stream when you load it into your Image. However, I don't think you can reset the position (i.e. "Seek") on a NetworkStream (your InputStream). Once you read it, it is gone.
One thing you can do though is to create a MemoryStream and use Stream.CopyTo to copy the contents into that. Then, you can do anything you like with it, including resetting the position to 0 to "read it a second time".
//example of resetting a stream named "s"
s.Position = 0;
Thanks guys for the reply they were very helpful but I fixed this issue by making slight changes on my code as below, I checked the image dimension after reading the input Stream. May be someone find this helpful.
public string ftpUpload(HttpPostedFileBase imagefile, string filename)
{
var sourceStream = imagefile.InputStream;
int BUFFER_SIZE = imagefile.ContentLength;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = sourceStream.Read(buffer, 0, BUFFER_SIZE);
if (!CheckLogoDimension(sourceStream))
{
sourceStream.Close();
return "error";
}
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpRootPath + "/" + filename);
request.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
request.Method = WebRequestMethods.Ftp.UploadFile;
Stream requestStream = request.GetRequestStream();
request.ContentLength = sourceStream.Length;
do
{
requestStream.Write(buffer, 0, bytesRead);
bytesRead = sourceStream.Read(buffer, 0, BUFFER_SIZE);
} while (bytesRead > 0);
sourceStream.Close();
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
return "Success";
}
A web application that receive and send a pdf file with signature. I send pdf file in httpwebrequest to the application. But not receive that pdf file with httpwebresponse ?
My code
byte[] pdfFile = File.ReadAllBytes("c:\\sample.pdf");
WebRequest request = WebRequest.Create("URL");
request.Credentials = new NetworkCredential("Username", "Password");
request.Proxy.Credentials = new NetworkCredential("Username", "Password");
request.Method = "POST";
request.ContentLength = pdfFile.Length;
request.ContentType = "application/pdf";
Stream stream = request.GetRequestStream();
stream.Write(pdfFile, 0, pdfFile.Length);
stream.Close();
WebResponse resp = request.GetResponse();
var buffer = new byte[4096];
MemoryStream memoryStream = new MemoryStream();
Stream responseStream =resp.GetResponseStream();
{
int count;
do
{
count = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write
(buffer, 0, responseStream.Read(buffer, 0, buffer.Length));
} while (count != 0);
}
resp.Close();
byte[] memoryBuffer = memoryStream.ToArray();
System.IO.File.WriteAllBytes(#"c:\sample1.txt", memoryBuffer);
int s = memoryBuffer.Length;
BinaryWriter binaryWriter =
new BinaryWriter(File.Open(#"c:\sample2.txt", FileMode.Create));
binaryWriter.Write(memoryBuffer);
binaryWriter.Close();
//Read Fully is :
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
One problem you have is in your reading:
int count;
do
{
count = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, responseStream.Read(buffer, 0, buffer.Length));
} while (count != 0);
You're reading the buffer twice each time through the loop. The bytes you read the first time are lost because you overwrite them. Your code should be:
int count;
do
{
count = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, count);
} while (count != 0);
Also: I don't understand why you're writing the PDF to the request stream. Are you trying to send the PDF to a server and have it send the same file back?
What, exactly, are you trying to do here?
I am trying to post data to server that accepts compressed data. The code below works just fine, but it is uncompressed. I have not worked with compression or Gzip beofre, so any help is appriciated.
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
request.Timeout = 600000;
request.Method = verb; // POST
request.Accept = "text/xml";
if (!string.IsNullOrEmpty(data))
{
request.ContentType = "text/xml";
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
request.ContentLength = byteData.Length;
// Here is where I need to compress the above byte array using GZipStream
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
}
}
XmlDocument xmlDoc = new XmlDocument();
HttpWebResponse response = null;
StreamReader reader = null;
try
{
response = request.GetResponse() as HttpWebResponse;
reader = new StreamReader(response.GetResponseStream());
xmlDoc.LoadXml(reader.ReadToEnd());
}
Do I gzip the entire byte array? Do I need to add other headers or remove the one that is already there?
Thanks!
-Scott
To answer the question you asked, to POST compressed data, all you need to do is wrap the request stream with a gzip stream
using (Stream postStream = request.GetRequestStream())
{
using(var zipStream = new GZipStream(postStream, CompressionMode.Compress))
{
zipStream.Write(byteData, 0, byteData.Length);
}
}
This is completely different than requesting a gzip response, which is a much more common thing to do.
I also received the "Cannot close stream until all bytes are written" error using code similar to tnyfst's. The problem was that I had:
request.ContentLength = binData.Length;
where binData is my raw data before the compression. Obviously the length of the compressed content would be different, so I just removed this line and ended up with this code:
using (GZipStream zipStream = new GZipStream(request.GetRequestStream(), CompressionMode.Compress))
{
zipStream.Write(binData, 0, binData.Length);
}
In Page_Load event:
Response.AddHeader("Content-Encoding", "gzip");
And for making compressed requests:
HttpWebRequest and GZip Http Responses by Rick Strahl
Try this extension method.
The stream will be left open (see the GZipStream constructor).
The stream position is set to 0 after the compression is done.
public static void GZip(this Stream stream, byte[] data)
{
using (var zipStream = new GZipStream(stream, CompressionMode.Compress, true))
{
zipStream.Write(data, 0, data.Length);
}
stream.Position = 0;
}
You can use the following test:
[Test]
public void Test_gzip_data_is_restored_to_the_original_value()
{
var stream = new MemoryStream();
var data = new byte[]{1,2,3,4,5,6,7,8,9,10};
stream.GZip(data);
var decompressed = new GZipStream(stream, CompressionMode.Decompress);
var data2 = new byte[10];
decompressed.Read(data2,0,10);
Assert.That(data, Is.EqualTo(data2));
}
For more information see: http://msdn.microsoft.com/en-us/library/hh158301(v=vs.110).aspx
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