Broken archive after receiving by FTP C# - c#

I try to send by FTP one .zip file. First I take one .txt file and added to archive .zip.
When I try to send this file everything is OK. But when a file is coming on the machine and I want to uncompress the .zip file is broken.
On the sender machine .zip file is OK. Only on the ftp machine is broken.
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
namespace SEND_Plovdiv
{
public class WebRequestGetExample
{
public static void Main()
{
string[] lineOfContents = File.ReadAllLines(#"C:\\M\send.txt");
string username = "";
string password = "";
foreach (var line in lineOfContents)
{
string[] tokens = line.Split(',');
string user = tokens[0];
string pass = tokens[1];
username = user;
password = pass;
}
string pathFile = #"C:\M\Telegrami\";
string zipPath = #"C:\M\Plovdiv.zip";
if (File.Exists(zipPath))
{
File.Delete(zipPath);
}
ZipFile.CreateFromDirectory(pathFile, zipPath, CompressionLevel.Fastest, false);
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://199.199.199.199/Plovdiv.zip");
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential(username, password);
// Copy the contents of the file to the request stream.
StreamReader sourceStream = new StreamReader(#"C:\M\Plovdiv.zip");
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();
Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
Console.ReadKey();
response.Close();
}
}
}
I dont know what exactly do this part of code:
StreamReader sourceStream = new StreamReader(#"C:\M\Plovdiv.zip");

Switch from using the StreamReader to BinaryReader. Zip files are binary files not UTF8.
Here's a sample:
using (FileStream fs = File.Open(#"c:\1.bin",FileMode.Open))
{
byte[] data = new BinaryReader(fs).ReadBytes((int)fs.Length);
Encoding.getstring....
}
StreamReader vs BinaryReader?

Related

ftp upload file corrupted in c# [duplicate]

This question already has an answer here:
Archive or image is corrupted after uploading to FTP and downloading back with FtpWebRequest
(1 answer)
Closed 5 years ago.
hello i have this code to upload image or word file through c# by using ftp.
the code works fine it uploads the file to ftp but file goes corrupted after uploading please advice what is wrong in this thanks
//FTP Server URL.
string ftp = "ftp://ftpip/";
//FTP Folder name. Leave blank if you want to upload to root folder.
string ftpFolder = "folder path to upload";
byte[] fileBytes = null;
//Read the FileName and convert it to Byte array.
string fileName = Path.GetFileName(FileUpload1.FileName);
using (StreamReader fileStream = new StreamReader(FileUpload1.PostedFile.InputStream))
{
fileBytes = Encoding.UTF8.GetBytes(fileStream.ReadToEnd());
fileStream.Close();
}
try
{
//Create FTP Request.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftp + ftpFolder + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
//Enter FTP Server credentials.
request.Credentials = new NetworkCredential("ftpuser", "ftppassowrd");
request.ContentLength = fileBytes.Length;
request.UsePassive = true;
request.UseBinary = true;
request.ServicePoint.ConnectionLimit = fileBytes.Length;
request.EnableSsl = false;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(fileBytes, 0, fileBytes.Length);
requestStream.Close();
}
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
lblMessage.Text += fileName + " uploaded.<br />";
response.Close();
}
catch (WebException ex)
{
throw new Exception((ex.Response as FtpWebResponse).StatusDescription);
}
You could use BinaryReader instead of getting the bytes as UTF8 encoding. You should change it;
using (StreamReader fileStream = new StreamReader(FileUpload1.PostedFile.InputStream))
{
fileBytes = Encoding.UTF8.GetBytes(fileStream.ReadToEnd());
fileStream.Close();
}
to
FileUpload1.PostedFile.InputStream.Seek(0, SeekOrigin.Begin);
using (var binaryReader = new BinaryReader(FileUpload1.PostedFile.InputStream))
{
fileBytes = binaryReader.ReadBytes(FileUpload1.PostedFile.ContentLength);
}

Can we unzip file in FTP server using C#

Can I extract the ZIP file in FTP and place this extracted file on the same location using C#?
It's not possible.
There's no API in the FTP protocol to un-ZIP a file on a server.
Though, it's not uncommon that one, in addition to an FTP access, have also an SSH access. If that's the case, you can connect with the SSH and execute the unzip shell command (or similar) on the server to decompress the files.
See C# send a simple SSH command.
If you need, you can then download the extracted files using the FTP protocol (Though if you have the SSH access, you will also have an SFTP access. Then, use the SFTP instead of the FTP.).
Some (very few) FTP servers offer an API to execute an arbitrary shell (or other) commands using the SITE EXEC command (or similar). But that's really very rare. You can use this API the same way as the SSH above.
If you want to download and unzip the file locally, you can do it in-memory, without storing the ZIP file to physical (temporary) file. For an example, see How to import data from a ZIP file stored on FTP server to database in C#.
Download via FTP to MemoryStream, then you can unzip, example shows how to get stream, just change to MemoryStream and unzip. Example doesn't use MemoryStream but if you are familiar with streams it should be trivial to modify these two examples to work for you.
example from: https://learn.microsoft.com/en-us/dotnet/framework/network-programming/how-to-download-files-with-ftp
using System;
using System.IO;
using System.Net;
using System.Text;
namespace Examples.System.Net
{
public class WebRequestGetExample
{
public static void Main ()
{
// 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();
response.Close();
}
}
}
decompress stream, example from: https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-compress-and-extract-files
using System;
using System.IO;
using System.IO.Compression;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
using (FileStream zipToOpen = new FileStream(#"c:\users\exampleuser\release.zip", FileMode.Open))
{
using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
{
ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
{
writer.WriteLine("Information about this package.");
writer.WriteLine("========================");
}
}
}
}
}
}
here is a working example of downloading zip file from ftp, decompressing that zip file and then uploading the compressed files back to the same ftp directory
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string location = #"ftp://localhost";
byte[] buffer = null;
using (MemoryStream ms = new MemoryStream())
{
FtpWebRequest fwrDownload = (FtpWebRequest)WebRequest.Create($"{location}/test.zip");
fwrDownload.Method = WebRequestMethods.Ftp.DownloadFile;
fwrDownload.Credentials = new NetworkCredential("anonymous", "janeDoe#contoso.com");
using (FtpWebResponse response = (FtpWebResponse)fwrDownload.GetResponse())
using (Stream stream = response.GetResponseStream())
{
//zipped data stream
//https://stackoverflow.com/a/4924357
byte[] buf = new byte[1024];
int byteCount;
do
{
byteCount = stream.Read(buf, 0, buf.Length);
ms.Write(buf, 0, byteCount);
} while (byteCount > 0);
//ms.Seek(0, SeekOrigin.Begin);
buffer = ms.ToArray();
}
}
//include System.IO.Compression AND System.IO.Compression.FileSystem assemblies
using (MemoryStream ms = new MemoryStream(buffer))
using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Update))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
FtpWebRequest fwrUpload = (FtpWebRequest)WebRequest.Create($"{location}/{entry.FullName}");
fwrUpload.Method = WebRequestMethods.Ftp.UploadFile;
fwrUpload.Credentials = new NetworkCredential("anonymous", "janeDoe#contoso.com");
byte[] fileContents = null;
using (StreamReader sr = new StreamReader(entry.Open()))
{
fileContents = Encoding.UTF8.GetBytes(sr.ReadToEnd());
}
if (fileContents != null)
{
fwrUpload.ContentLength = fileContents.Length;
try
{
using (Stream requestStream = fwrUpload.GetRequestStream())
{
requestStream.Write(fileContents, 0, fileContents.Length);
}
}
catch(WebException e)
{
string status = ((FtpWebResponse)e.Response).StatusDescription;
}
}
}
}
}
}
}
If you're trying to unzip the files in place after they have been ftp uploaded, you will need to run a server side script with proper permissions that can be fired from within your c# application, or c# ssh as already described earlier.

Download zip file from the server and parsing it

I am trying to download a zipped file from the server and trying to show the content of each files in zipped folder to the view.
I wrote a separate code where the file is on my laptop and I ran across each file and dislpayed the content such as
static void Main(string[] args)
{
string filePath = "C:\\ACL Data\\New folder\\files.zip";
var zip= new ZipInputStream(File.OpenRead(filePath));
var filestream=new FileStream(filePath,FileMode.Open,FileAccess.Read);
ZipFile zipfile = new ZipFile(filestream);
ZipEntry item;
while ((item = zip.GetNextEntry()) != null)
{
Console.WriteLine(item.Name);
using (StreamReader s = new StreamReader(zipfile.GetInputStream(item)))
{
Console.WriteLine(s.ReadToEnd());
}
}
Console.Read();
}
I am using sharplibzip library to implement this
This is the case when the zip file is located locally in the system. My next task scenario is what if the zipped file is located on the server. I am figuring out the way to implement it, below is the code what I assume should work
static void Main(string[] args)
{
string url = "https://test/code/304fd9c6-7e53-42a2-845a-624608bfd2ce.zip";
WebRequest webRequest = WebRequest.Create(url);
webRequest.Method = "GET";
WebResponse webResponse = webRequest.GetResponse();
var zip = new ZipInputStream(webResponse.GetResponseStream());
ZipEntry item1;
//var zip= new ZipInputStream(File.OpenRead(filePath));
var filestream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
ZipFile zipfile = new ZipFile(filestream);
ZipEntry item;
while ((item = zip.GetNextEntry()) != null)
{
Console.WriteLine(item.Name);
using (StreamReader s = new StreamReader(zipfile.GetInputStream(item)))
{
Console.WriteLine(s.ReadToEnd());
}
}
Console.Read();
}
I am stuck at this part: var filestream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
This expect the first parameter to be path of the zip file. Since in the new scenario zip file is located remotely on the server. What should be the parameter in this case?
Your original code opens the stream twice on the following rows, which I think is causing some confusion:
var zip= new ZipInputStream(File.OpenRead(filePath));
var filestream=new FileStream(filePath,FileMode.Open,FileAccess.Read);
There is an overload to the ZipFile constructor that takes "any" Stream rather than specifically a FileStream, which you - unsurprisingly - can only create for files.
However, you cannot use the stream returned by GetResponseStream directly, because it's CanSeek property is false. This is because it's a NetworkStream, which can only be read once from beginning to end. SharpZipLib needs random access to read the file contents.
Depending on the size of the ZIP file, loading it in memory may be an option. If you expect large files, writing it to a temporary file may be better.
This should do the trick, without using both ZipInputStream and ZipFile, by enumerating through ZipFile instead:
string url = "https://test/code/304fd9c6-7e53-42a2-845a-624608bfd2ce.zip";
WebRequest webRequest = WebRequest.Create(url);
webRequest.Method = "GET";
WebResponse webResponse = webRequest.GetResponse();
using (var responseStream = webResponse.GetResponseStream())
using (var ms = new MemoryStream())
{
// Copy entire file into memory. Use a file if you expect a lot of data
responseStream.CopyTo(ms);
var zipFile = new ZipFile(ms);
foreach (ZipEntry item in zipFile)
{
Console.WriteLine(item.Name);
using (var s = new StreamReader(zipFile.GetInputStream(item)))
{
Console.WriteLine(s.ReadToEnd());
}
}
}
Console.Read();
PS: starting .NET 4.5, there is support for ZIP files built in. See the ZipArchive class.

FtpWebRequest Download File Incorrect Size

I’m using the following code to download a file from a remote ftp server:
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath);
request.KeepAlive = true;
request.UsePassive = true;
request.UseBinary = true;
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(userName, password);
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
using (StreamWriter destination = new StreamWriter(destinationFile))
{
destination.Write(reader.ReadToEnd());
destination.Flush();
}
The file that I’m downloading is a dll and my problem is that it is being altered by this process in some way. I know this because the file size is increasing. I have a suspicion that this section of code is at fault:
destination.Write(reader.ReadToEnd());
destination.Flush();
Can anyone offer any ideas as to what may be wrong?
StreamReader and StreamWriter work with character data, so you are decoding the stream from bytes to characters and then encoding it back to bytes again. A dll file contains binary data, so this round-trip conversion will introduce errors. You want to read bytes directly from the responseStream object and write to a FileStream that isn't wrapped in a StreamWriter.
If you are using .NET 4.0 you can use Stream.CopyTo, but otherwise you will have to copy the stream manually. This StackOverflow question has a good method for copying streams:
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
while (true)
{
int read = input.Read(buffer, 0, buffer.Length);
if (read <= 0)
return;
output.Write(buffer, 0, read);
}
}
So, your code will look like this:
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (FileStream destination = File.Create(destinationFile))
{
CopyStream(responseStream, destination);
}

How do I programmatically save an image from a URL?

How do I programmatically save an image from a URL? I am using C# and need to be able grab images from a URL and store them locally. ...and no, I am not stealing :)
It would be easier to write something like this:
WebClient webClient = new WebClient();
webClient.DownloadFile(remoteFileUrl, localFileName);
You just need to make a basic http request using HttpWebRequest for the URI of the image then grab the resulting byte stream then save that stream to a file.
Here is an example on how to do this...
'As a side note if the image is very large you may want to break up br.ReadBytes(500000) into a loop and grab n bytes at a time writing each batch of bytes as you retrieve them.'
using System;
using System.IO;
using System.Net;
using System.Text;
namespace ImageDownloader
{
class Program
{
static void Main(string[] args)
{
string imageUrl = #"http://www.somedomain.com/image.jpg";
string saveLocation = #"C:\someImage.jpg";
byte[] imageBytes;
HttpWebRequest imageRequest = (HttpWebRequest)WebRequest.Create(imageUrl);
WebResponse imageResponse = imageRequest.GetResponse();
Stream responseStream = imageResponse.GetResponseStream();
using (BinaryReader br = new BinaryReader(responseStream ))
{
imageBytes = br.ReadBytes(500000);
br.Close();
}
responseStream.Close();
imageResponse.Close();
FileStream fs = new FileStream(saveLocation, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
try
{
bw.Write(imageBytes);
}
finally
{
fs.Close();
bw.Close();
}
}
}
}
An example in aspx (c#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
public partial class download_file_from_url : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string url = "http://4rapiddev.com/wp-includes/images/logo.jpg";
string file_name = Server.MapPath(".") + "\\logo.jpg";
save_file_from_url(file_name, url);
Response.Write("The file has been saved at: " + file_name);
}
public void save_file_from_url(string file_name, string url)
{
byte[] content;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
using (BinaryReader br = new BinaryReader(stream))
{
content = br.ReadBytes(500000);
br.Close();
}
response.Close();
FileStream fs = new FileStream(file_name, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
try
{
bw.Write(content);
}
finally
{
fs.Close();
bw.Close();
}
}
}
Author: HOAN HUYNH
ASP.Net C# Download Or Save Image File From URL
My solution is pre save the image to de disk and then usa as a normal saved image:
remoteFile = "http://xxx.yyy.com/image1.png";
localFile = "c:\myimage.png";
WebClient webClient = new WebClient();
webClient.DownloadFile(remoteFile, localFile);

Categories