utorok, 05 marec 2019 12:00 Written by 2586 times
Rate this item
(0 votes)

Stahovanie suborov z FTP cez PROXY

 

Predstavíme vám jednoduchý a funkčný kód ktorý stiahne súbor z FTP servera cez PROXY a nakopíruje ho do vybranej cesty na vase PC.

Priznám sa, že na internete je minimum funkčných kódov na sťahovanie súborov z FTP cez PROXY, tak som sa rozhodol napísať svoj vlastný, no čo je najpodstatnejšie, overený a funkčný zdrojový kód. Napísal som funkciu Download_from_FTP, ktorá má 2 vstupné a jeden výstupný parameter. Vstupné parameter RemoteFile – meno súboru, ktorý sa má stiahnuť, Path – cesta kam sa má súbor nakopírovať na vase PC môžete samozrejme kopírovať súbor aj inam) a výstupný parameter ErrMsg, ktorý sa vyplní chybovou hláškou v prípade zlyhania sťahovania súboru. Funkcia má návratovú hodnotu typu Boolean, čiža ak uspeje je hodnota true a ka nie, false. Zadefinoval som si vlastnú triedu na výnimky ProxySocketException ktorú si uložte do ľubovoľného súboru *.cs a pripojte potom cez klauzulu using do skriptu. Ďalej sú k funkcii potrebné ešte funkcie GetFileLengthFromHeader a SearchBytes, ktoré si nakopírujte k funkcii Download_from_FTP. Konštanty na pripojenie, t.j. meno FTP a PROXY a autentikačné údaje sú farebne vyznačené vo funkcii a sú na pohľa zrejmé. Zdrojový kód som kompiloval vo verzii C# Microsoft Visual Studio Enterprise C# 2017 verzia 15.5.1, Target framework: .NET Framework 4.5.1. Dúfam, že niekomu bude kód nápomocný. S pozdravom.

Kód v c# (ProxySocketException ):

     public class ProxySocketException : Exception
    {
        public ProxySocketException()
        {
        }

        public ProxySocketException(string message) : base(message)
        {
        }

        public ProxySocketException(string message, Exception innerException) : base(message, innerException)
        {
        }

        protected ProxySocketException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    }

 

Kód v c# (Download_from_FTP ):

System.Int64 GetFileLengthFromHeader(string[] Header)
        {
            System.Int64 l = 0;
            foreach (string item in Header)
            {
                if (item.Length > 15 && item.Substring(0, 15).CompareTo("Content-Length:") == 0)
                {
                    string strLen = item.Split(" ".ToCharArray())[1];
                    return Convert.ToInt64(strLen);
                }
           }
            return l;
        }

        int SearchBytes(byte[] haystack, byte[] needle)
        {
            int len = needle.Length;
            int limit = haystack.Length - len;
            int k;
            for (int i = 0; i <= limit; i++)
            {
                k = 0;
                for (; k < len; k++)
                {
                    if (needle[k] != haystack[i + k]) break;
                }
                if (k == len) return i;
            }
            return -1;
        }
    }

 

Kód v c# (Hlavná funkcia: ):

bool Download_from_FTP(string RemoteFile, string Path, out string ErrMsg)
        {
            const int RECV_SIZE = 64 * 1024;

            ErrMsg = string.Empty;
            try
            {
                var proxyAuthB64Str = Convert.ToBase64String(Encoding.ASCII.GetBytes("PROXY_USERNAME" + ":" + "PROXY_PASSWORD"));
                var sendStr = "GET http://" + "FTP_USERNAME" + ":" + "FTP_PASSWORD" + "@" + " FTP IP alebo domenove meno " + "PATH – cesta k suboru na FTP" + RemoteFile + " HTTP/1.1\n"
                            + "Host: " + "FTP IP alebo domenove meno" + "\n"
                            + "User-Agent: Mozilla/4.0 (compatible; Eradicator; dotNetClient)\n"
                            + "Proxy-Authorization: Basic " + proxyAuthB64Str + "\n"
                            + "Content-Type: application/octet-stream\n"
                            + "Connection: close\n\n";
                var sendBytes = Encoding.ASCII.GetBytes(sendStr);

                using (var ProxySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    ProxySocket.Connect("PROXY_HOST – IP alebo domenove meno", "3128");
                    if (!ProxySocket.Connected) throw new ProxySocketException ();
                    // sending data protocol to FTP ...
                    ProxySocket.Send(sendBytes);

                    // buffer for the received data from FTP ...
                    byte[] Buffer = new byte[RECV_SIZE];
                    // read first packet, Buffr_size - size of first read packet ...
                    int Buffer_size = ProxySocket.Receive(Buffer, RECV_SIZE, SocketFlags.Partial);
                    if (Buffer_size == 0) throw new ProxySocketException("No bytes recieved from " + " FTP IP alebo domenove meno " + "PATH – cesta k suboru na FTP");

                    // Check result of recieved data from the header ...
                    var Header = new string(Encoding.ASCII.GetChars(Buffer)).Split("\r\n".ToCharArray());
                    var responseFirstLine = Header.Take(1).ElementAt(0);
                    var httpResponseDescription = Regex.Replace(responseFirstLine, @"HTTP/1\.\d (\d+) (\w+)", "$2");
                    // check, if received data OK ...
                    if (httpResponseDescription != "OK")
                    {
                        throw new ProxySocketException("Error: " + responseFirstLine);
                    }

                    // size of the buffer read from the first packet ...
byte[] FILE_SEPARATOR = new byte[] { 0x0D, 0x0A, 0x0D, 0x0A };
                    int File_offset = SearchBytes(Buffer, FILE_SEPARATOR);
                    if (File_offset == -1)
                    {
                        throw new Exception("Recieved data error - no joined file data: " + new string(Encoding.ASCII.GetChars(Buffer)));
                    }
                    File_offset += FILE_SEPARATOR.Length;

                    // expected size of the downloaded file ...
                    System.Int64 FileSizeHeader = GetFileLengthFromHeader(Header);

                    // Checker of the downloaded file ...
                    System.Int64 FileSize = 0;

                    StreamWriter fstream = new StreamWriter(Path + RemoteFile);
                    try
                    {
                        // Write first downloaded file packet placed behind the header data ...
                        fstream.BaseStream.Write(Buffer, File_offset, Buffer_size - File_offset);
                        FileSize = Buffer_size - File_offset;
                        // write the next packets ...
                        while ((Buffer_size = ProxySocket.Receive(Buffer, RECV_SIZE, SocketFlags.Partial)) > 0)
                        {
                            fstream.BaseStream.Write(Buffer, 0, Buffer_size);
                            FileSize += Buffer_size;
                        }
                    }
                    finally
                    {
                        fstream.Close();
                        fstream.Dispose();
                        fstream = null;
                    }

                    sendBytes = null;
                    sendStr = null;
                    Buffer = null;
                    Header = null;

                    if (FileSize != FileSizeHeader)
                        throw new ProxySocketException("Unable to download file " + RemoteFile + ". Not all bytes downloaded.");
                }

                return ErrMsg.Length == 0;
            }
            catch (Exception ex)
            {
                ErrMsg = ex.Message;
                return false;
            }
        }

 

 

Last modified on utorok, 05 marec 2019 12:23
Alojz Benďák

Autor je administrátor webu a venuje sa programovaniu takmer 23 rokov.

  • prvý kontakt s počítačmi na strednej škole - PMD 1,2,3, PP06, Atari, Sinclair (programovanie v jazyku: strojový kód, basic a pascal):  2 roky
  • na VŠ - jazyky Turbo pascal a Turbo C: 1rok
  • programovanie databázového ekonomického širokoškálneho software v Delphi a C++ Borland (databázy Paradox): 8 rokov v Codex s.r.o. Nitra
  • programovanie webových aplikácií na databázach MySQL a MS SQL server: 1 roky na živnosť (firmy: Hermes Nitra, Schindler v Bratislave)
  • pracoval ako DBA v Homecredit Brno a vo VÚB Bratislava ako vyvojár + optimalizácie v SQL a PL/SQL na Oracle 11g (firma Accenture)
  • programoval programy pre súkromné firmy pre HW na skenovanie povrchov nádrží pre skladovanie tekutých palív (pristroj Leica)
  • momentálne pracuje ako DBA pod Oracle 11g a ako vyvojár vnútropodnikových databázových aplikacií v PHP, SQL, C++, C# a interface v PL/SQL: 11 rokov
  • ďalej programuje s HTML, CSS, Ajax, Javascript, VBA, MS visual C++ a C# malé podporné aplikácie
  • certifikát SQL expert for Oracle 11g   
  • spolupracuje a aktívne učí pre počítačové firmy: Lapis, IVIT v Nitre