I have very strange problem when I upload files to my FTP (zip or gif) files.
I am creating a zip file with code and upload it with code to FTP. I can open any of this files type when I create them on my local disk. But when I upload any of this to FTP and than download it show me a message for .zip file as "unexpected end of archive" , and for .gif file type after I download them and try to open in XP Windows picture and fax viewer "Drawing failed" :
I use this code for uploading to FTP:
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.tim.com/" + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential(ftpuser,ftppass);
// Copy the contents of the file to the request stream.
StreamReader sourceStream = new StreamReader(filePath +"\\"+ fileName);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
request.KeepAlive = false;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
This code:
StreamReader sourceStream = new StreamReader(filePath +"\\"+ fileName);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
You're reading the bytestream as text with a specific encoding (UTF8)... but GIF and ZIP are binary files, not text files. The encoding is mangling them.
Try using something like ReadAllBytes:
byte[] fileContents = File.ReadAllBytes("filepath");
You are reading binary data to string (assuming it utf8) and converts it back to bytes array. That's completely wrong.
Related
I am connecting to an SFTP server using SSH.NET and trying to read an image into a stream for displaying it in my web page.
SftpClient client = connectToServer(IP,user,pwd);
string remotePath = client.WorkingDirectory.ToString() + dto.Directory + "/";
FileStream fs = new FileStream(remotePath + dto.FileName,FileMode.Open);
Stream strm = fs;
The above code throws an invalid characters exception. I am not sure if the reason for it is because of the filename on the server i.e. all these files are stored with * delimiter i.e. Text1*Text2*Text3.00.png.
If it is, is there any other way to read the stream?
I have also tried to read from HttpResponse.OutputStream but that throws a read/seek invalid exception.
HttpResponse response = HttpContext.Current.Response;
Stream strm = response.OutputStream;
Are there any other ways to read such image files?
This is the working code code for the same functionality using FtpWebRequest.
var request = (FtpWebRequest)WebRequest.Create(serverUri);
request.UsePassive = true;
request.UseBinary = true;
request.Credentials =//
request.Method = WebRequestMethods.Ftp.DownloadFile;
response = (FtpWebResponse)await request.GetResponseAsync();
Stream responseStream = response.GetResponseStream();
I am changing it to SFTP using SSH.NET.
Is there a way to get the same output as GetResponseStream() with SSH.NET?
If you need to obtain Stream API to a file on SFTP server, use SSH.NET SftpClient.Open[Read]:
Stream fs = client.OpenRead(remotePath);
I can't use WebClient, before anyone suggests that because it makes my legit application seem like a virus to McAfee. So please don't suggest that.
I have a binary.txt file stored on my server. It is approximately 1,240kb. However, HttpWebRequest downloads random amounts from 1,300kb to 1,700kb.
HttpWebRequest httpRequest = (HttpWebRequest)
WebRequest.Create("http://deviantsmc.com/binary.txt");
httpRequest.Method = WebRequestMethods.Http.Get;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream httpResponseStream = httpResponse.GetResponseStream();
byte[] buffer = new byte[1240];
int bytesRead = 0;
StringBuilder sb = new StringBuilder();
//FileStream fileStream = File.Create(#"tcontent.txt");
while ((bytesRead = httpResponseStream.Read(buffer, 0, 1240)) != 0)
{
sb.Append(Encoding.ASCII.GetString(buffer));
//fileStream.Write(buffer, 0, bytesRead);
}
File.WriteAllText(#"tcontent1.txt", sb.ToString());
(The contents of the binary.txt file on the server are in ASCII, therefore I get the Encoding string to ASCII as well).
This is how I encoded that text file (on that server)
My file is basically this:
byte[] bytes = File.ReadAllBytes("binary.txt");
String encBytes = Encoding.ASCII.GetString(bytes);
File.WriteAllText(file("binary.txt"), encBytes);
I contacted the AV company about the WebDownloader being seen as some malicious import in C#, but they didn't get back to me, so I'm forced to use HttpWebRequest.
If your only goal is to fetch that binary and write it to disk you can simply copy the stream to a file with the CopyTo method that exists on a Stream object.
Your file looks like a broken zip file btw, given the first characters that are PK, and is used in the zip specificaton.
From wikipedia:
Viewed as an ASCII string this reads "PK", the initials of the inventor Phil Katz. Thus, when a .ZIP file is viewed in a text editor the first two bytes of the file are usually "PK".
I used 7-zip to open your file as the Windows default didn't accept it as a valid file. It contains a manifest.mf file but the content itself seems missing. the file itself has a size of 1.269.519 bytes.
HttpWebRequest httpRequest = (HttpWebRequest)
WebRequest.Create("http://deviantsmc.com/binary.txt");
httpRequest.Method = WebRequestMethods.Http.Get;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream httpResponseStream = httpResponse.GetResponseStream();
// create and open a FileStream, using calls dispose when done
using(var fs= File.Create(#"c:\temp\bin.7z"))
{
// Copy all bytes from the responsestream to the filestream
httpResponseStream.CopyTo(fs);
}
I think you should write the entire binary data to the local file, instead of encoding it segmentally, you can try this:
HttpWebRequest httpRequest = (HttpWebRequest)
WebRequest.Create("http://deviantsmc.com/binary.txt");
httpRequest.Method = WebRequestMethods.Http.Get;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream httpResponseStream = httpResponse.GetResponseStream();
using (BinaryReader responseReader = new BinaryReader(httpResponseStream.GetResponseStream()))
{
byte[] bytes = responseReader.ReadBytes((int)response.ContentLength);
using (BinaryWriter sw = new BinaryWriter(File.OpenWrite("tcontent1.txt")))
{
sw.Write(bytes);
sw.Flush();
sw.Close();
}
}
Hope this can help
Now I know how to copy files from one directory to another, this is really simple.
But now I need to do the same with files from FTP server. Can you give me some example how to get file from FTP while changing its name?
Take a look at How to: Download Files with FTP or downloading all files in directory ftp and c#
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://www.contoso.com/test.htm");
request.Method = WebRequestMethods.Ftp.DownloadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential ("anonymous","janeDoe#contoso.com");
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("Download Complete, status {0}", response.StatusDescription);
reader.Close();
reader.Dispose();
response.Close();
Edit
If you want to rename file on FTP Server take a look at this Stackoverflow question
Easiest way
The most trivial way to download a binary file from an FTP server using .NET framework is using WebClient.DownloadFile.
It takes an URL to the source remote file and a path to the target local file. So you can use a different name for the local file, if you need that.
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.DownloadFile(
"ftp://ftp.example.com/remote/path/file.zip", #"C:\local\path\file.zip");
Advanced options
If you need greater control, that WebClient does not offer (like TLS/SSL encryption, ASCII mode, active mode, etc), use FtpWebRequest. Easy way is to just copy an FTP response stream to FileStream using Stream.CopyTo:
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(#"C:\local\path\file.zip"))
{
ftpStream.CopyTo(fileStream);
}
Progress monitoring
If you need to monitor a download progress, you have to copy the contents by chunks yourself:
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(#"C:\local\path\file.zip"))
{
byte[] buffer = new byte[10240];
int read;
while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, read);
Console.WriteLine("Downloaded {0} bytes", fileStream.Position);
}
}
For GUI progress (WinForms ProgressBar), see:
FtpWebRequest FTP download with ProgressBar
Downloading folder
If you want to download all files from a remote folder, see
C# Download all files and subdirectories through FTP.
I've just written a simple FTP console app to upload files on a local server to a remote FTP site. Everything seems to be working fine until it comes to actually transferring the file. For some reason instead of uploading the file to the specified FTP site it stores the entire file locally with no in the Debug folder with no file type and named the same as the ip of the FTP site. I'm thinking that this has something to do with Visual Studio's debugging. Can anybody give me some guidance on this?
Here is the code I'm using to attempt to upload each file in a string array to the FTP site.
private static void Upload(string ftpServer, string userName, string password, string filename)
{
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential(userName, password);
client.UploadFile(ftpServer, "STOR", filename);
}
}
Use this method instead of that one,it worked for me.
//Directory sands for Remote Server Directory ,it must create if dir not exist
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://serverIP/directory/file");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential ("username","password");
// Copy the contents of the file to the request stream.
StreamReader sourceStream = new StreamReader("testfile.txt");
byte [] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
source- http://msdn.microsoft.com/en-us/library/ms229715.aspx
Try this way instead: http://msdn.microsoft.com/en-us/library/ms229715.aspx
I want to create a file with a .aspx extension(or any other extension) completely in memory. Can this be done?
Right now I have a memory stream that has all the stuff I want to write to this file but I don't actually want to create a physical file on the server since then I probably have to enable write permissions for my server. What I want to do is create the file in memory and upload via ftpWebRequest.
Edit.
I must be doing something wrong because I get weird stuff in my file so weird I can't even paste it into my posts.
Basically it is a bunch of squares between everything. Like it almost seems like it fills it in for the spaces. Like If I look closely I will see the tag still but it will have a square between each letter.
Here is a portion of my code. Maybe I am using the wrong encoding?
using (MemoryStream memory = new MemoryStream())
{
UnicodeEncoding uniEncoding = new UnicodeEncoding();
// readByline is the first bunch of data I want for my new file.
memory.Write(uniEncoding.GetBytes(readByLine), 0, readByLine.Length);
// second bunch of data I want for my new file.
memory.Write(uniEncoding.GetBytes(html), 0, html.Length);
// the follow code just figure out the end of the file that I am
// trying to extract some information out of.
string readToEnd = reader.ReadToEnd();
int endIndex = readToEnd.IndexOf(END_FLAG);
endIndex += END_FLAG.Length;
string restOfFile = readToEnd.Substring(endIndex);
// once found I write it the memory stream.
memory.Write(uniEncoding.GetBytes(restOfFile),0,restOfFile.Length);
// now I want to upload my file. I have the same file name already
// existing on the server? Do I have to tell it override it?
FtpWebRequest request2 = (FtpWebRequest)WebRequest.Create(path);
request2.Method = WebRequestMethods.Ftp.UploadFile;
request2.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
// now I am trying your code.
byte[] fileContents = memory.ToArray();
using (Stream writer = request2.GetRequestStream())
{
writer.Write(fileContents, 0, fileContents.Length);
}
FtpWebResponse test = (FtpWebResponse)request2.GetResponse();
return Content("test");
}
You can convert the MemoryStream to a byte[] and then use WebClient.UploadData to upload the file with FTP to some server without writing it on the client to disk first:
webClient.UploadData(
"ftp://remoteserver/remotepath/file.aspx"
memoryStream.ToArray());
FtpWebRequest works as well, of course, but needs a few more lines of code:
FtpWebRequest ftpRequest;
FtpWebResponse ftpResponse;
ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://..."));
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Proxy = null;
ftpRequest.UseBinary = true;
ftpRequest.Credentials = new NetworkCredential("UserName", "Password");
using (Stream stream = ftpRequest.GetRequestStream())
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.WriteLine("<html><head><title>Hello World</title></head>...");
}
ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
Well, such a file is really just plain text, with certain formatting - HTML 4.0, XHTML or such.
So yes, you can create that in memory - inside e.g. a StringBuilder, and then save it back out to disk using a StreamWriter or some other means.
If you can't or don't want to write it out to disk, you can of course also put it into a MemoryStream, and interfaces that can read from any arbitrary stream can read from the memory stream, too.
Check out the MSDN docs on FtpWebRequest and on GetRequestStream() method. It has a sample on how to upload from a stream to FTP directly:
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
request.Method = WebRequestMethods.Ftp.UploadFile;
// this could be your MemoryStream, of course, that you're reading from
StreamReader sourceStream = new StreamReader(fileName);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
request.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
// check the response, do whatever you need to do with it
response.Close();