I want the user to upload a file and save it to a stream.
Here is the code so far:
private void Submit_ServerClick(object sender, System.EventArgs e)
{
fn = System.IO.Path.GetFileName(File1.PostedFile.FileName);
}
you could do like this
string filePath = uploadFile(fileUploadControl.FileContent);
private string uploadFile(Stream serverFileStream)
{
string filename = ConfigurationManager.AppSettings["FileUploadTempDir"] +
DateTime.Now.ToString("yyyyMMddhhmm") + "_" +
Customer.GetCustomerName(CustomerId).Replace(" ", "_") + ".txt";
try
{
int length = 256;
int bytesRead = 0;
Byte[] buffer = new Byte[length];
// write the required bytes
using (FileStream fs = new FileStream(filename, FileMode.Create))
{
do
{
bytesRead = serverFileStream.Read(buffer, 0, length);
fs.Write(buffer, 0, bytesRead);
}
while (bytesRead == length);
}
serverFileStream.Dispose();
return filename;
}
catch (Exception ex)
{
lblErrorMessage.Text += "An unexpeded error occured uploading the file. " + ex.Message;
return string.Empty;
}
}
i hope it will helps you...
The object that FileUpload.PostedFile returns has an InputStream property you can read the uploaded file data from.
Looks like this one http://support.microsoft.com/kb/323246
string fn = System.IO.Path.GetFileName(File1.PostedFile.FileName);
string SaveLocation = Server.MapPath("Data") + "\\" + fn;
try
{
File1.PostedFile.SaveAs(SaveLocation);
Response.Write("The file has been uploaded.");
}
catch ( Exception ex )
{
Response.Write("Error: " + ex.Message);
//Note: Exception.Message returns a detailed message that describes the current exception.
//For security reasons, we do not recommend that you return Exception.Message to end users in
//production environments. It would be better to put a generic error message.
}
Related
I am trying to send the large file(greater than 2 GB) via Sockets in C#. I am sending it in chunks of 10 MB.
I will explain what is my approach. From client side, I will send the chunk and will wait for confirmation from server(if that chunk has been received or not). After receving confirmation, I will send another chunk and will again wait for confimation from server for that chunk. The loop will continue till all file data has been sent to. After successful sent operation of file, will close the connection from client side.
Client Side Code:
try
{
DateTime startdate = DateTime.Now;
string ori_text = btn_Send_Files.Text;
btn_Send_Files.Text = "Do not click already sending...";
btn_Send_Files.Refresh();
IPAddress[] ipAddress = Dns.GetHostAddresses("localhost");
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5656);
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
clientSock.Connect(ipEnd);
label1.Text = label1.Text + "\nConnected to:" + ipEnd.Address.ToString();
label1.Refresh();
string fileName = "CCCCCC.zip"; //It has size greater than 2 GB
string filePath = #"C:\Users\CCCCCC\Downloads\";
byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
label1.Text = label1.Text + "\nSending the file:" + fileName;
label1.Refresh();
FileInfo fi = new FileInfo(filePath + fileName);
int max = 1024 * 1024 * 10;
long start = 0, bytesRead = 0;
FileStream fileStream = new FileStream(filePath + fileName, FileMode.Open, FileAccess.Read);
max = max - (4 + fileNameByte.Length);
byte[] tmpserver = new byte[100];
using (fileStream)
{
int i = 0;
while (start < fi.Length)
{
i += 1;
label1.Text = label1.Text + "\nSending " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
fileStream.Seek(start, SeekOrigin.Begin);
if (max > (fi.Length - start))
max = Convert.ToInt32(fi.Length - start);
byte[] buffer = new byte[max];
byte[] clientData = new byte[4 + fileNameByte.Length + max];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
bytesRead = fileStream.Read(buffer, 0, max);
start += max;
buffer.CopyTo(clientData, 4 + fileNameByte.Length);
clientSock.Send(clientData);
Array.Clear(clientData, 0, clientData.Length);
Array.Clear(buffer, 0, buffer.Length);
Array.Clear(fileNameLen, 0, fileNameLen.Length);
Array.Clear(clientData, 0, clientData.Length);
clientData = null;
buffer = null;
fileNameLen = null;
GC.Collect();
label1.Text = label1.Text + "\nWaiting for confirmation of " + i.ToString() + " block of file:" + fileName;
int serverdata = clientSock.Receive(tmpserver);
if (serverdata == 0)
{
clientSock.Shutdown(SocketShutdown.Both);
clientSock.Close();
break;
}
else
{
label1.Text = label1.Text + "\nReceived confirmation for " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
}
}
}
clientSock.Close();
DateTime enddate = DateTime.Now;
TimeSpan diff = startdate - enddate;
label1.Text = label1.Text + "\nFile "+ fileName + " has been sent to:"+ ipEnd.Address.ToString();
label1.Text = label1.Text + "\nTime Taken to sent the file(seconds):" + Math.Abs(diff.Seconds).ToString();
label1.Refresh();
btn_Send_Files.Text = ori_text;
btn_Send_Files.Refresh();
}
catch (Exception ex)
{
MessageBox.Show("File Sending fail." + ex.ToString());
}
Server Side Code:
try
{
label1.Text = label_text;
label1.Refresh();
string ori_btn_text = btn_Start_Server.Text;
btn_Start_Server.Text = "Do not click already waiting...";
btn_Start_Server.Refresh();
label1.Text = label1.Text + "\nWaiting for client";
label1.Refresh();
string receivedPath = ConfigurationManager.AppSettings["Location"];
Socket clientSock = sock.Accept();
label1.Text = label1.Text + "\nServer Started and connected to client" + clientSock.LocalEndPoint + "\nWaiting for the file to receive";
label1.Refresh();
int max = 1024*1024*10;
string logfile = receivedPath + "\\serverlog.log";
if (File.Exists(logfile))
{
File.Delete(logfile);
}
FileStream fs = File.Create(logfile);
byte[] serverdata = new byte[100];
string fileName = "";
int fileNameLen = 0, fileDataLen = 0;
int i = 0;
BinaryWriter bWrite = null;
while (true)
{
i += 1;
byte[] clientData = new byte[max];
int receivedBytesLen = clientSock.Receive(clientData);
if (receivedBytesLen <= 0)
break;
string tmp = "\nStarted:" + i;
fs.Write(Encoding.ASCII.GetBytes(tmp), 0, Encoding.ASCII.GetBytes(tmp).Length);
if (i == 1)
{
fileNameLen = BitConverter.ToInt32(clientData, 0);
fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
fileDataLen = BitConverter.ToInt32(clientData, 4);
if (File.Exists(receivedPath + fileName))
{
File.Delete(receivedPath + fileName);
}
bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Create));
label1.Text = label1.Text + "\nReceiving File:" + fileName;
}
label1.Text = label1.Text + "\nReceived " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
Array.Clear(clientData, 0, clientData.Length);
clientData = null;
GC.Collect();
clientSock.Send(serverdata);
label1.Text = label1.Text + "\nSent confirmation for " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
}
if (bWrite != null)
{
bWrite.Flush();
bWrite.Dispose();
bWrite.Close();
}
fs.Close();
label1.Text = label1.Text + "\nFile has been received:" + fileName;
label1.Refresh();
MessageBox.Show("File has been received:" + fileName);
btn_Start_Server.Text = ori_btn_text;
btn_Start_Server.Refresh();
}
catch (Exception ex)
{
MessageBox.Show("File Receiving fail." + ex.ToString());
}
It works fine on locally but over the network getting timeout exception on .receive() method on server side.
I strongly suggest you don't try to reinvent the wheel. There is no need to mess around with sockets and chunks of files.
Instead just open the file as a FileStream and copy it straight into a NetworkStream, which you can get using TcpClient (and TcpListener for the server).
You should also convert this code to be fully async.
public async void btn_Send_Files_Click(object sender, EventArgs e)
{
DateTime startdate = DateTime.Now;
try
{
string ori_text = btn_Send_Files.Text;
btn_Send_Files.Text = "Do not click already sending...";
btn_Send_Files.Enabled = false;
await SendFileAsync();
label1.Text += $"\nFile {fileName} has been sent to: {ipEnd.Address}\nTime Taken to sent the file(seconds):{Math.Abs(diff.Seconds)}";
}
catch (Exception ex)
{
MessageBox.Show("File Sending fail." + ex.ToString());
}
finally
{
DateTime enddate = DateTime.Now;
TimeSpan diff = startdate - enddate;
btn_Send_Files.Text = ori_text;
btn_Send_Files.Enabled = true;
}
}
private async Task SendFiles()
{
string fileName = "CCCCCC.zip"; //It has size greater than 2 GB
string filePath = #"C:\Users\CCCCCC\Downloads\";
using (var fileStream = new FileStream(Path.Combine(filePath, fileName), FileMode.Open, FileAccess.Read))
using (var client = new TcpClient())
{
await client.ConnectAsync(IPAddress.Any, 5656); // replace with remote IP
label1.Text += $"\nConnected to:{client.Client.RemoteEndPoint}";
label1.Refresh();
using (var netStream = client.GetStream())
{
await fileStream.CopyToAsync(netStream);
}
}
}
Server-side code
public async void btn_Start_Server_Click(object sender, EventArgs e)
{
try
{
label1.Text = label_text;
string ori_btn_text = btn_Start_Server.Text;
btn_Start_Server.Text = "Do not click already waiting...";
btn_Start_Server.Enabled = false;
label1.Text = label1.Text + "\nWaiting for client";
label1.Refresh();
await WaitForFile("SomeFilename");
label1.Text = label1.Text + "\nFile has been received:" + fileName;
MessageBox.Show("File has been received:" + fileName);
}
catch (Exception ex)
{
MessageBox.Show("File Receiving fail." + ex.ToString());
}
finally
{
btn_Start_Server.Text = ori_btn_text;
btn_Start_Server.Enabled = true;
}
}
private Task WaitForFile(string fileName)
{
string receivedPath = ConfigurationManager.AppSettings["Location"];
var listener = new TcpListener(IPAddress.Any, 5656); // local IP to listen at, do not change
try
{
listener.Start();
using (var client = await listener.AcceptTcpClientAsync())
using (var networkStream = client.GetStream())
using (var fileStream = new FileStream(Path.Combine(receivedPath, fileName), FileMode.Create, FileAccess.Write))
{
label1.Text = $"{label1.Text}\nServer Started and connected to client {client.Client.RemoteEndPoint}\nWaiting for the file to receive";
label1.Refresh();
await networkStream.CopyToAsync(fileStream);
}
}
finally
{
if (listener.Active)
listener.Stop();
}
}
Your existing code also passes the filename through the stream. I'm sure you will manage to adapt the above to do the same.
Also, if you want to show progress, it could get more complicated. You may need to write your own FileStream-derived class.
Hello I'm trying to implement a server and client couple that can transfer files of any kind and any size but there is a problem I somehow corrupt files. I tried lots of methods but can't figure it out. So basicly I can connect ,I can understand which file does client want, and can send it through sockets. When I try to open that file it shows me an error message(Tried winrar, mp4, avi files) Here is my code:
//Server
private void Receive(string receivedFileName, string fileSize)
{
try
{
int receivedBytesLen = 0;
byte[] incomingFile = new byte[int.Parse(fileSize)];
activity.AppendText("Preparing to download... \n");
while (incomingFile != null && int.Parse(fileSize) > receivedBytesLen)
{
tempSocket.Receive(incomingFile);
receivedBytesLen = incomingFile.Length;
int fileNameLen = BitConverter.ToInt32(incomingFile, 0);
File.WriteAllBytes(fileDir + "//" + receivedFileName, incomingFile);
}
activity.AppendText("File saved to " + fileDir + "\n");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//////////////////////////////////////////////////////////////////////
//server option 2
private void Receive(string receivedFileName, string fileSize)
{
try
{
byte[] incomingFile = new byte[10124 * 5000];
activity.AppendText("Preparing to download... \n");
BinaryWriter bWrite = new BinaryWriter(File.Open(folderBrowserDialog1.SelectedPath + "//" + receivedFileName, FileMode.Append));
int receivedBytesLen = tempSocket.Receive(incomingFile, incomingFile.Length, 0);
int fileNameLen = BitConverter.ToInt32(incomingFile, 0);
//string fileName = Encoding.UTF8.GetString(incomingFile, 4, fileNameLen);
//bWrite.Write(incomingFile, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
while (receivedBytesLen > 0)
{
receivedBytesLen = tempSocket.Receive(incomingFile, incomingFile.Length, 0);
if (receivedBytesLen == 0)
{
bWrite.Close();
}
else
{
bWrite.Write(incomingFile, 0, receivedBytesLen);
}
}
activity.AppendText("File saved to " + fileDir + "\n");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/////////////////////////////////////////////////////////////////////
//client
private void Upload_Click(object sender, EventArgs e)
{//Uploads selected file after clicking upload button.
try
{
if (clientSocket.Connected)
{
byte[] buffer = new byte[1024];
byte[] sendingFile = null;
sendingFile = File.ReadAllBytes(openFileDialog1.FileName);
FileInfo f = new FileInfo(openFileDialog1.FileName);
string fileSize = f.Length.ToString();
buffer = Encoding.Default.GetBytes(getUserName.Text + "Upload" + openFileDialog1.SafeFileName + "size" + fileSize + "end");
clientSocket.Send(buffer);
activityLog.AppendText("Sending File \n");
int bytesToBeSent = sendingFile.Length;
int bytesActuallySent = 0;
while(bytesActuallySent < bytesToBeSent){
bytesActuallySent += clientSocket.Send(sendingFile, bytesActuallySent, bytesToBeSent -bytesActuallySent, 0);
}
activityLog.AppendText("File Sent.\n");
}
}
catch(Exception ex){
MessageBox.Show(ex.Message);
}
}
server option #2 is better. But there are some improvements
socket receive buffer is limited decided by OS, generally is 8192
use FileStream in client and server and do not forget to close filestream after file download
client:
FileStream fileStream = new FileStream(filePath, FileMode.Open)
byte[] buff = new byte[8192];
do
{
bytesRead = fileStream.Read(buff, 0, buff.Length);
sock.send(dataSock, buff, bytesRead);
}while (bytesRead > 0);
fileStream.close();
server:
FileStream fileStream = new FileStream(filePath, FileMode.Open)
do
{
bytesRead = sock.receive(buff, 0, buff.Lenght);
fileStream.Write(buff, 0, bytesRead );
}while (bytesRead > 0);
fileStream.close();
In order to satisfy ANY sized file you need an option #3, one that reads a block of bytes til all bytes are received, your option #1 wouldn't do so well on a 3 GIG file running on 2 GIG box...
Here is a link: http://www.yoda.arachsys.com/csharp/readbinary.html
I like option #2 from this link.
However in the example they write to a memoryStream, you should write to a filestream, the target file.
Thanks for reading, I genuinely appreciate that I am asking a lot of whoever reads this.
I have to cut a physical file into 4096 kB chunks for upload. I can pick them up from the "other end" easy enough and remake them.
I appreciate there is a lot of information in this post and this one but I am struggling how to fit this all together elegantly
The idea is simply to cut files bigger than 4096kB into smaller parcels. To make it worse: if there is a way to synchronously Queue the send of the files without them having to be put on the local disk (i.e. work only in memory) I would really like that..
//Pseudocode:
Queue queue = new Queue();
byte[] currentChunk ;
int i =0;
while(currentChunk = openFileinChunks(filename, 4194304)) //4096 kB
{
HTTPPoster mypost = new HTTPPoster();
mypost.add(currentChunk);
//need comparison here - to know when last loop is happening to use different name :-/ for this next bit
mypost.uploadedName(filename+"."+ i.ToString().PadLeft(6, '0');
queue.Enqueue(mypost);
i++;
}
do
{
HTTPPoster Post = (HTTPPoster) queue.Dequeue();
Post.Run();
} while (queue.Count != 0);
class HTTPPoster{
byte[] sendable;
string tmpname;
public void add(byte[] toPost)
{
sendable = toPost;
}
public void uploadedName(string name)
{
tmpname = name;
}
public void Run()
{
//[preferably some condensed reworked code to replace this] **
}
}
**: Upload files with HTTPWebrequest (multipart/form-data)
I found this article http://blogs.msdn.com/b/johan/archive/2009/03/30/1080526.aspx very handy when trying to do something similar.
The approach in that article is relatively straightforward: you set up the web request then write chunks of data to the stream. However, by setting AllowWriteStreamBuffering to false, you prevent the request from buffering the whole file in memory.
The problem with your current approach is that it appears to keep everything in memory - this might cause you problems with larger files.
What does the server component of this look like? That will probably dictate the precise method you use to send the file.
Edit:
What about this?
int bytesRead;
int bufferSize = 4194304;
byte[] buffer = new byte[bufferSize];
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
int i = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
string postFileName = Path.GetFileName(filePath) + "." + i++.ToString().PadLeft(10, '0');
if (bytesRead < bufferSize)
{
postFileName = Path.GetFileName(filePath) + ".terminus";
}
PostFileChunk(buffer, bytesRead, postFileName);
}
}
This will read the file in blocks of 4MB, then call the PostFileChunk method (your HTTPPoster could come in to play here) to send the data to the server.
Keep in mind that when you are writing the chunk to the post in your Run method, use the bytesRead - because we are reusing the buffer, if the last read is less than bufferSize, it will still contain some of the data from the previous read. bytesRead will ensure that these characters don't get written.
this works, I have reduced it to 4096 B (not 4096kB) "chunks" but the principle is the same
NB: there is a small amount of object referencing that is my own - a thing I use called the jsonFolder and jsonDomain, which basically holds the username, password and url and file info.. you should be able to follow this logic though.. i will try to make the time to post this to a tutorial (including the PHP serverSide code, and the incron rebuilder)
/******
* the terminus file format is weird
* basically it goes like this
* tmp/myfilename.ext.00000000001 4kB
* tmp/myfilename.ext.00000000002 4kB
* tmp/myfilename.ext.00000000003 4kB
* tmp/myfilename.ext.00000000004 4kB
* tmp/myfilename.ext.terminus <=4kB
* this will re-built here to
* dir/myfilename.ext >16kB <20kB
*/
class classActionType_clientPush : classActionType
{
string relpath = "";
jsonFolder myFolder;
jsonDomain myDomain;
Queue<HTTPPoster> queue = new Queue<HTTPPoster>();
/// <param name="relativeLocalFilePath">
/// this "relativeLocalFilePath" refers to path RE: the ~localFolder~ - this class will cut the file and upload it in 4096kB chunks
/// </param>
/// <param name="folder">
/// use this for the folder pathing
/// </param>
/// <param name="domain">
/// this is for the credentials and the url
/// </param>
public void setPath(string relativeLocalFilePath, jsonFolder folder, jsonDomain domain)
{
string tmppath = folder.localFolder + relativeLocalFilePath;
if (File.Exists(tmppath))
{
relpath = relativeLocalFilePath;
myFolder = folder;
myDomain = domain;
}
else
{
throw new Exception("classActionType_clientPull.setPath():tmppath \"" + tmppath + "\" does not already exist");
}
}
public override void action()
{
if (relpath == "")
{
throw new Exception("classActionType_clientPull.action():relpath cannot be \"\"");
}
/***
* split it into chunks and copy file to server
*/
try
{
int bytesRead;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
string filePath = myFolder.localFolder + relpath;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
int i = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
string postFileName = Path.GetFileName(filePath) + "." + i++.ToString().PadLeft(10, '0');
if (bytesRead < bufferSize)
{
postFileName = Path.GetFileName(filePath) + ".terminus";
}
HTTPPoster mypost = new HTTPPoster();
mypost.add(buffer);
mypost.setBytes(bytesRead);
mypost.setDomain(this.myDomain);
mypost.uploadedName(postFileName);
queue.Enqueue(mypost);
Debug.WriteLine(" nof: HTTPPoster.action() loop counter " + i + "");
}
}
do
{
HTTPPoster Post = (HTTPPoster)queue.Dequeue();
Post.Run();
} while (queue.Count != 0);
}
catch (Exception ex)
{
Debug.WriteLine(" nof: HTTPPoster.action() failed\r\n" + ex.Message + "\r\n" + ex.StackTrace);
}
}
}
class HTTPPoster
{
byte[] sendable;
string filename;
int bytes;
jsonDomain myDomain;
public void add(byte[] b)
{
sendable = b;
}
public void uploadedName(string p)
{
filename = p;
}
public void setDomain(jsonDomain domain)
{
myDomain = domain;
}
public void setBytes(int bytesRead)
{
bytes = bytesRead;
}
public void Run()
{
try
{
/***
* this does the actual post (!gulp)
*/
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(myDomain.url + "/io/clientPush.php");
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
string formitem;
byte[] formitembytes;
classHasher hash = new classHasher();
rs.Write(boundarybytes, 0, boundarybytes.Length);
formitem = string.Format(formdataTemplate, "username", myDomain.user);
formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
rs.Write(boundarybytes, 0, boundarybytes.Length);
formitem = string.Format(formdataTemplate, "password", hash.Decrypt(myDomain.password, "saltysaltsalt"));
formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, "file", filename, "multipart/mixed");
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
rs.Write(sendable, 0, bytes);
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream myStream = wresp.GetResponseStream();
StreamReader myReader = new StreamReader(myStream);
Debug.WriteLine(" nof: HTTPPoster.Run() all ok \r\n" + myReader.ReadToEnd());
}
catch (Exception ex)
{
Debug.WriteLine(" nof: HTTPPoster.Run() finished\r\n" + ex.Message + "\r\n" + ex.StackTrace);
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
catch (Exception ex)
{
Debug.WriteLine(" nof: HTTPPoster.Run() !ERROR! \r\n" + ex.Message + "\r\n" + ex.StackTrace);
}
}
}
My solution:
void LikeThat(byte[] file)
{
var ms = new System.IO.MemoryStream(file);
var b= new byte[4096];
while (ms.Length > 0)
{
ms.Read(b, 0, 4096);
//now b contains your chunk, just transmit it!
}
}
Im just trying to save a file to disk using a posted stream from jquery uploadify
I'm also getting Parameter not valid.
On adding to the error message so i can tell where it blew up in production im seeing it blow up on:
var postedBitmap = new Bitmap(postedFileStream)
any help would be most appreciated
public string SaveImageFile(Stream postedFileStream, string fileDirectory, string fileName, int imageWidth, int imageHeight)
{
string result = "";
string fullFilePath = Path.Combine(fileDirectory, fileName);
string exhelp = "";
if (!File.Exists(fullFilePath))
{
try
{
using (var postedBitmap = new Bitmap(postedFileStream))
{
exhelp += "got past bmp creation" + fullFilePath;
using (var imageToSave = ImageHandler.ResizeImage(postedBitmap, imageWidth, imageHeight))
{
exhelp += "got past resize";
if (!Directory.Exists(fileDirectory))
{
Directory.CreateDirectory(fileDirectory);
}
result = "Success";
postedBitmap.Dispose();
imageToSave.Save(fullFilePath, GetImageFormatForFile(fileName));
}
exhelp += "got past save";
}
}
catch (Exception ex)
{
result = "Save Image File Failed " + ex.Message + ex.StackTrace;
Global.SendExceptionEmail("Save Image File Failed " + exhelp, ex);
}
}
return result;
}
Use image converter to load from byte array:
ImageConverter imageConverter = new System.Drawing.ImageConverter();
Image image = imageConverter.ConvertFrom(byteArray) as Image;
http://forums.asp.net/t/1109959.aspx
It seems your stream type is not valid for Bitmap object, try to copy stream to MemoryStream, and give MemoryStream as a parameter of Bitmap
and remove second dispose as #Aliostad mentoined
something like this
public string SaveImageFile(Stream postedFileStream, string fileDirectory, string fileName, int imageWidth, int imageHeight)
{
string result = "";
string fullFilePath = Path.Combine(fileDirectory, fileName);
string exhelp = "";
if (!File.Exists(fullFilePath))
{
try
{
using(var memoryStream = new MemoryStream())
{
postedFileStream.CopyTo(memoryStream);
memoryStream.Position = 0;
using (var postedBitmap = new Bitmap(memoryStream))
{
.........
}
}
}
catch (Exception ex)
{
result = "Save Image File Failed " + ex.Message + ex.StackTrace;
Global.SendExceptionEmail("Save Image File Failed " + exhelp, ex);
}
}
return result;
}
I am trying to download files from an ftp server using C# and ftpwebrequest. I can get the bytes using BinaryReader, but when I try to read the stream using br.ReadBytes(int), I get an error that BinaryReader does not support seek operations.
Does anyone know how best to read the bytes so I can write them to a file?
Here's the full method:
public void DownloadFile(String fileName)
{
Logger.Info("starting to download file: " + fileName);
try
{
var downloadFileRequest = (FtpWebRequest)WebRequest.Create(FtpServer + "//" + fileName);
downloadFileRequest.Credentials = new NetworkCredential(FtpUsername,FtpPassword);
downloadFileRequest.Method = WebRequestMethods.Ftp.DownloadFile;
downloadFileRequest.UseBinary = true;
ServicePoint sp = downloadFileRequest.ServicePoint;
sp.ConnectionLimit = 2;
Logger.Info("getting ftp response for download file for " + fileName);
try
{
var downloadResponse = (FtpWebResponse)downloadFileRequest.GetResponse();
Logger.Info("getting ftp response stream for " + fileName);
try
{
Stream downloadStream = downloadResponse.GetResponseStream();
Logger.Info("File Download status: {0}", downloadResponse.StatusDescription.Trim());
Logger.Info("getting binary reader for " + fileName);
try
{
using ( var downloadReader = new BinaryReader(downloadStream))
{
String destinationFilePath= Path.Combine(LocalFolder, fileName);
Logger.Info("writing response stream to " + destinationFilePath);
try
{
using (var downloadWriter = new BinaryWriter(System.IO.File.Open(destinationFilePath, FileMode.Create)))
{
downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length));
}
Logger.Info("successfully saved " + destinationFilePath);
}
catch (Exception ex)
{
Logger.Info("could not save " + destinationFilePath+ " b/c: " + ex.Message);
}
}
}
catch (Exception ex)
{
Logger.Info("could not read " + fileName + " b/c: " + ex.Message);
}
}
catch (Exception ex)
{
Logger.Info("could not open download stream for " + fileName + " b/c: " + ex.Message);
}
finally
{
downloadResponse.Close();
}
}
catch (Exception ex)
{
Logger.Info("could not get ftp response stream for " + fileName + " b/c: " + ex.Message);
}
}
catch (Exception ex)
{
Logger.Info("could not get ftp request stream for " + fileName + " b/c: " + ex.Message);
}
}
This runs as part of an ongoing service, so I don't want to throw errors that would stop the service. Instead, I'm writing to a log. Here are the contents of the log for this method:
2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|starting to download file: 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.1421|INFO|xxx.Web.Controllers.FtpController|getting ftp response for download file for 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|getting ftp response stream for 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6661|INFO|xxx.Web.Controllers.FtpController|File Download status: 125 Data connection already open; Transfer starting.
2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|getting binary reader for 2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6721|INFO|xxx.Web.Controllers.FtpController|writing response stream to C:\\Resumes\\2009-10-06155728Z_metadata.txt
2009-10-07 16:33:29.6951|INFO|xxx.Web.Controllers.FtpController|could not save C:\\Resumes\\2009-10-06155728Z_metadata.txt b/c: This stream does not support seek operations.
I've been working on this way too long, so any help would be appreciated!
Thanks!!
You shouldn't rely on Stream.Length, its possible it could be wrong. You just need to read all of the bytes in a while loop until there are no more bytes to read.
MemoryStream ms = new MemoryStream();
byte[] chunk = new byte[4096];
int bytesRead;
while ((bytesRead = downloadStream.Read(chunk, 0, chunk.Length)) > 0)
{
ms.Write(chunk, 0, bytesRead);
}
From there, all the read data is in the MemoryStream, and you can initialize the BinaryReader with that.
Darkassassin's answer works great! Here's the code I finally got to work before I saw his post. It's slightly different b/c it writes directly to the file rather than to the memory stream.
I replaced this line:
downloadWriter.Write(downloadReader.ReadBytes((int)downloadStream.Length));
with this:
var buffer = new byte[BufferSize];
int readCount = downloadStream.Read(buffer, 0, BufferSize);
while (readCount > 0)
{
downloadWriter.Write(buffer, 0, readCount);
readCount = downloadStream.Read(buffer, 0, BufferSize);
}
(BufferSize = 4096)
Thanks again for the quick help!!