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; } }