Advertisement
Guest User

Untitled

a guest
Aug 23rd, 2016
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.21 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Concurrent;
  4. using System.Threading.Tasks;
  5. using System.Net;
  6.  
  7. using System.Windows.Forms; // for test code
  8. using System.IO; // for test code
  9. using System.Diagnostics; // for test code
  10.  
  11. namespace FTPTest2
  12. {
  13. class Program
  14. {
  15. const int cNumberOfFilesToSend = 10;
  16. const string cFTPfolderPath = "ftp://localhost:21/testfolder/";
  17. const string cFTPUsername = "Anonymous";
  18. const string cFTPPassword = "";
  19.  
  20. private static byte[] FileBytes;
  21.  
  22. // testing functions (for example usage). Sends copies of the selected file to a ftp server.
  23. [STAThread]
  24. static void Main(string[] args)
  25. {
  26.  
  27. FTPManager.StartTransferBackgroundTask();
  28.  
  29. OpenFileDialog choosefiletosenddialog = new OpenFileDialog();
  30. DialogResult dialogresult = choosefiletosenddialog.ShowDialog();
  31.  
  32. if (dialogresult != DialogResult.OK)
  33. {
  34. return;
  35. }
  36.  
  37. string selectedfilepath = choosefiletosenddialog.FileName;
  38.  
  39.  
  40. string selectedfilename = Path.GetFileNameWithoutExtension(selectedfilepath);
  41. string selectedfileextension_withdot = Path.GetExtension(selectedfilepath);
  42.  
  43. using(FileStream selectedfilestream = new FileStream(selectedfilepath, FileMode.Open))
  44. {
  45. // note: a 3rd party API only allows me to get data using a byte array
  46. if (selectedfilestream.Length > int.MaxValue)
  47. {
  48. MessageBox.Show("Selected file is too big.");
  49. return;
  50. }
  51.  
  52. FileBytes = new byte[selectedfilestream.Length];
  53.  
  54. selectedfilestream.Read(FileBytes, 0, (int) selectedfilestream.Length);
  55. }
  56.  
  57. // note that FTPWebrequest would get a lot of "system error" exceptions if I sent 100,000 files using a threadpool for each file
  58. // transfer operation.
  59. for (int fileindex = 0; fileindex < cNumberOfFilesToSend; fileindex++)
  60. {
  61. string filename = String.Format("{0}_{1}{2}", selectedfilename, fileindex.ToString(), selectedfileextension_withdot);
  62. System.Threading.ThreadPool.QueueUserWorkItem(Thread_Main, filename);
  63.  
  64. }
  65.  
  66. Console.WriteLine("Waiting for all jobs to finish...");
  67.  
  68. while (!FTPManager.AllJobsComplete())
  69. {
  70. System.Threading.Thread.Sleep(100);
  71. }
  72.  
  73. Console.WriteLine("All jobs complete. Hit Enter to quit...");
  74. Console.ReadLine();
  75. }
  76.  
  77. static void Thread_Main(object filename)
  78. {
  79. if (!(filename is string))
  80. {
  81.  
  82. Debug.Fail("Invalid parameter type");
  83. return;
  84. }
  85.  
  86. FTPManager.AddJob((string) filename, FileBytes, cFTPfolderPath, cFTPUsername, cFTPPassword);
  87. }
  88.  
  89. }
  90.  
  91.  
  92. class Stub
  93. {
  94. public static void Log_Error(string message)
  95. {
  96. Console.WriteLine(message);
  97. }
  98. }
  99.  
  100. internal class FTPManager
  101. {
  102. // note: for the sake of this test this was set lower than normal.
  103. // 10000 is more reasonable on some networks.
  104. internal const int cFTPTimeout_ms = 1000;
  105.  
  106. private static ConcurrentQueue<FTPFileJob> FTPJobs = new ConcurrentQueue<FTPFileJob>();
  107. private static Task FTPTransferTask;
  108.  
  109. // @CR: What do you guys think of this? The .NET framework reference source occasionally makes internal exceptions.
  110. internal class GenericFTPException : Exception
  111. {
  112. public GenericFTPException() : base() { }
  113.  
  114. public GenericFTPException(string message) : base(message) { }
  115.  
  116. public GenericFTPException(string message, Exception inner) : base(message, inner) { }
  117. }
  118.  
  119. private class FTPFileJob
  120. {
  121. internal readonly string FileName;
  122. internal readonly byte[] Data;
  123. internal readonly string FTPFolderUrl;
  124. internal readonly string Username;
  125. internal readonly string Password;
  126.  
  127. internal FTPFileJob(string filename, byte[] filedata, string ftpfolderurl, string username, string password)
  128. {
  129. this.FileName = filename;
  130. this.Data = filedata;
  131. this.FTPFolderUrl = ftpfolderurl;
  132. this.Username = username;
  133. this.Password = password;
  134.  
  135. }
  136. }
  137.  
  138. internal static void StartTransferBackgroundTask()
  139. {
  140. if (FTPManager.FTPTransferTask != null)
  141. {
  142. return;
  143. }
  144.  
  145. FTPManager.FTPTransferTask = new Task(ProcessJobs);
  146. FTPManager.FTPTransferTask.Start();
  147. }
  148.  
  149. private static void ProcessJobs()
  150. {
  151. try
  152. {
  153. while (true)
  154. {
  155.  
  156. FTPFileJob ftpjob;
  157.  
  158. if (FTPManager.FTPJobs.TryDequeue(out ftpjob))
  159. {
  160. FTPManager.SendJob(ftpjob);
  161. }
  162.  
  163. else
  164. {
  165. System.Threading.Thread.Sleep(100);
  166. }
  167.  
  168. }
  169. }
  170. catch (System.Threading.ThreadInterruptedException)
  171. {
  172. }
  173. }
  174.  
  175. internal static void AddJob(string filename, byte[] filedata, string ftpfolderurl, string username, string password)
  176. {
  177. FTPManager.FTPJobs.Enqueue(new FTPFileJob(filename, filedata, ftpfolderurl, username, password));
  178. }
  179.  
  180. internal static bool AllJobsComplete()
  181. {
  182. return FTPManager.FTPJobs.IsEmpty;
  183. }
  184.  
  185. private static void SendJob(FTPFileJob ftpjob )
  186. {
  187. try
  188. {
  189. FTPManager.SendDataToFTP_Throws(ftpjob.Data, ftpjob.FTPFolderUrl, ftpjob.FileName, ftpjob.Username, ftpjob.Password);
  190. }
  191.  
  192. catch(GenericFTPException ftpexception)
  193. {
  194. Stub.Log_Error(ftpexception.Message);
  195. }
  196. }
  197.  
  198. internal static bool SendDataToFTP_Throws(byte [] data, string ftpfolderurl, string filename, string username, string password)
  199. {
  200. FtpWebRequest ftpwebrequest;
  201. string filepath = ftpfolderurl + filename;
  202.  
  203. try
  204. {
  205. ftpwebrequest = (FtpWebRequest) FtpWebRequest.Create(ftpfolderurl + filename);
  206. ftpwebrequest.Method = WebRequestMethods.Ftp.UploadFile;
  207. ftpwebrequest.Credentials = new NetworkCredential(username, password);
  208.  
  209. ftpwebrequest.Timeout = cFTPTimeout_ms;
  210. ftpwebrequest.UseBinary = true;
  211. ftpwebrequest.KeepAlive = false;
  212.  
  213. //read in data from the file to a byte buffer
  214. using(System.IO.Stream tWebRequestWriterStream = ftpwebrequest.GetRequestStream())
  215. {
  216. tWebRequestWriterStream.Write(data, 0, data.Length);
  217.  
  218. }
  219.  
  220. using(FtpWebResponse response = (FtpWebResponse) ftpwebrequest.GetResponse())
  221. {
  222. //note that ClosingData is the status code returned if everything's ok
  223. if (response.StatusCode == FtpStatusCode.ClosingData)
  224. {
  225. return true;
  226. }
  227.  
  228. else
  229. {
  230. throw new GenericFTPException("File '" + filepath + "' upload to FTP failed: (" + response.StatusCode + "): " + response.StatusDescription);
  231. }
  232. }
  233. }
  234. catch(System.IO.IOException ioexception)
  235. {
  236. //this will occur if:
  237. //- I kick the user that's transferring the file using the Filezilla server admin window
  238. throw new GenericFTPException("Failed to upload file '" + filepath + "' to FTP: " + ioexception.Message, ioexception);
  239. }
  240. catch(System.Net.WebException webexception)
  241. {
  242. //this will occur if:
  243. //- You try to send a file that is already on the server
  244. //- The server can't be reached
  245. throw new GenericFTPException("Failed to upload file '" + filepath + "' to FTP: " + webexception.Message, webexception);
  246. }
  247. catch(ArgumentOutOfRangeException argumentoutofrangeexception)
  248. {
  249. //This is a strange one, it only happens sporadically.
  250. //I get a long string of FTP timeouts, followed by this exception.
  251. //see this post for more details: https://social.msdn.microsoft.com/Forums/vstudio/en-US/5f4e0689-75bf-49f5-9854-d12e79aae84f/ftpwebrequest-argumentoutofrangeexception-millisecondstimeout?forum=netfxbcl
  252. throw new GenericFTPException("Failed to upload file '" + filepath + "' to FTP: .NET Framework internal FTP indexing error. Full info:nn" + argumentoutofrangeexception.ToString());
  253. }
  254. }
  255. }
  256. }
  257.  
  258. // note: This code can be considered public domain, or the absolute minimum licensing restrictions that CR allows. If you like it feel free to use it.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement