9

Can I extract the ZIP file in FTP and place this extracted file on the same location using C#?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Nithin
  • 1,376
  • 12
  • 29

3 Answers3

18

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#.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • It is possible, see Aaron. S. answer above for how to solve the problem. – Nathan Prather Dec 18 '19 at 17:07
  • @NathanPrather Aaron's answer downloads the ZIP to local machine, extracts and uploads individual files to the server. That's for sure not what most people imagine under *"unzip file in FTP server"*. -- So, no it is **not possible** to do what the OP asked for. + Not to mention that the upload code in the answer will break any binary file. --- That does not mean that his answer cannot be useful for someone (like you). – Martin Prikryl Dec 18 '19 at 17:47
4

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;
                        }
                    }
                }
            }
        }
    }
}
Aaron. S
  • 467
  • 4
  • 12
  • 1
    but after unzipping in memory stream I have to upload it to ftp right ? Actually I want all this done in a single ftp request.. – Nithin Sep 07 '17 at 06:11
  • sounds like you have a three step process? 1. download via ftp, 2. unzip, 3. upload via ftp? is this the order you are looking for? I gave two examples on how to first download via ftp and second how to unzip. Let me tailor the answer with something more specific, yes? – Aaron. S Sep 07 '17 at 16:51
  • 1
    Your upload code will work for text files only + `ContentLength` is not used with FTP. – Martin Prikryl Sep 07 '17 at 18:50
  • 2
    hmm, ContentLength was used in the MSDN example I used so if its not used, as you suggest, why are they? https://learn.microsoft.com/en-us/dotnet/framework/network-programming/how-to-upload-files-with-ftp and the zip file contained bitmaps not text files – Aaron. S Sep 07 '17 at 18:58
  • 1
    1) Even MSDN can be wrong. 2) That means that you have corrupted the bitmaps during an upload. – Martin Prikryl Sep 08 '17 at 06:31
  • I agree that the MSDN can be wrong, in this case no. I tested the code I provided as any programmer should. there were no issues with any media files. – Aaron. S Sep 11 '17 at 15:13
  • 1
    @Aaron.S (I didn't get a notification about your response, as you did not use `@`) - Absolutely not, just test a .jpg in .zip. It will get corrupted after the upload. I've tested with your exact code, without any modification. – Martin Prikryl Dec 13 '17 at 15:53
1

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.