在製造業的某些工藝中,可能會對產品進行拍照,這時須要監聽圖片文件並上傳到服務器進行保存。一開始,想將圖片的二進制數據轉換成string類型,而後經過webservice上傳,可是報錯「HTTP 狀態 400 失敗: Bad Request」。畢竟,webservice使用的是HTTP協議,若是想傳文件的話,有FTP協議幹嗎不用。而後在網上找了個C#使用FTP的幫助類(有點改動):html
static public class FtpHelper { //基本設置 static private string path = @"ftp://" + ConfigurationManager.AppSettings["ServerIp"] + "/"; //目標路徑 static private string ftpip = ConfigurationManager.AppSettings["ServerIp"]; //ftp IP地址 static private string username = ConfigurationManager.AppSettings["Username"];//ftp用戶名 static private string password = ConfigurationManager.AppSettings["Password"];//ftp密碼 //獲取ftp上面的文件和文件夾 public static string[] GetFileList(string dir) { string[] downloadFiles; StringBuilder result = new StringBuilder(); FtpWebRequest request; try { request = (FtpWebRequest)FtpWebRequest.Create(new Uri(path)); request.UseBinary = true; request.Credentials = new NetworkCredential(username, password);//設置用戶名和密碼 request.Method = WebRequestMethods.Ftp.ListDirectory; request.UseBinary = true; WebResponse response = request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string line = reader.ReadLine(); while (line != null) { result.Append(line); result.Append("\n"); Console.WriteLine(line); line = reader.ReadLine(); } // to remove the trailing '\n' result.Remove(result.ToString().LastIndexOf('\n'), 1); reader.Close(); response.Close(); return result.ToString().Split('\n'); } catch (Exception ex) { Console.WriteLine("獲取ftp上面的文件和文件夾:" + ex.Message); downloadFiles = null; return downloadFiles; } } /// <summary> /// 獲取文件大小 /// </summary> /// <param name="file">ip服務器下的相對路徑</param> /// <returns>文件大小</returns> public static int GetFileSize(string file) { StringBuilder result = new StringBuilder(); FtpWebRequest request; try { request = (FtpWebRequest)FtpWebRequest.Create(new Uri(path + file)); request.UseBinary = true; request.Credentials = new NetworkCredential(username, password);//設置用戶名和密碼 request.Method = WebRequestMethods.Ftp.GetFileSize; int dataLength = (int)request.GetResponse().ContentLength; return dataLength; } catch (Exception ex) { Console.WriteLine("獲取文件大小出錯:" + ex.Message); return -1; } } /// <summary> /// 文件上傳 /// </summary> /// <param name="filePath">原路徑(絕對路徑)包括文件名</param> /// <param name="fileName">上傳的文件名</param> /// <param name="objPath">目標文件夾:服務器下的相對路徑 不填爲根目錄</param> public static void FileUpLoad(string filePath, string fileName, string objPath = "") { string url = path; if (objPath != "") url += objPath + "/"; try { FtpWebRequest reqFTP = null; //待上傳的文件 (全路徑) try { FileInfo fileInfo = new FileInfo(filePath); using (FileStream fs = fileInfo.OpenRead()) { long length = fs.Length; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(url + fileName)); //設置鏈接到FTP的賬號密碼 reqFTP.Credentials = new NetworkCredential(username, password); //設置請求完成後是否保持鏈接 reqFTP.KeepAlive = false; //指定執行命令 reqFTP.Method = WebRequestMethods.Ftp.UploadFile; //指定數據傳輸類型 reqFTP.UseBinary = true; using (Stream stream = reqFTP.GetRequestStream()) { //設置緩衝大小 int BufferLength = 5120; byte[] b = new byte[BufferLength]; int i; while ((i = fs.Read(b, 0, BufferLength)) > 0) { stream.Write(b, 0, i); } } } } catch (Exception ex) { } } catch (Exception ex) { } } /// <summary> /// 刪除文件 /// </summary> /// <param name="fileName">服務器下的相對路徑 包括文件名</param> public static void DeleteFileName(string fileName) { try { FileInfo fileInf = new FileInfo(ftpip + "" + fileName); string uri = path + fileName; FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); // 指定數據傳輸類型 reqFTP.UseBinary = true; // ftp用戶名和密碼 reqFTP.Credentials = new NetworkCredential(username, password); // 默認爲true,鏈接不會被關閉 // 在一個命令以後被執行 reqFTP.KeepAlive = false; // 指定執行什麼命令 reqFTP.Method = WebRequestMethods.Ftp.DeleteFile; FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); response.Close(); } catch (Exception ex) { Console.WriteLine("刪除文件出錯:" + ex.Message); } } /// <summary> /// 新建目錄 上一級必須先存在 /// </summary> /// <param name="dirName">服務器下的相對路徑</param> public static void MakeDir(string dirName) { try { string uri = path + dirName; FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); // 指定數據傳輸類型 reqFTP.UseBinary = true; // ftp用戶名和密碼 reqFTP.Credentials = new NetworkCredential(username, password); reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory; FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); response.Close(); } catch (Exception ex) { Console.WriteLine("建立目錄出錯:" + ex.Message); } } /// <summary> /// 刪除目錄 上一級必須先存在 /// </summary> /// <param name="dirName">服務器下的相對路徑</param> public static void DelDir(string dirName) { try { string uri = path + dirName; FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); // ftp用戶名和密碼 reqFTP.Credentials = new NetworkCredential(username, password); reqFTP.Method = WebRequestMethods.Ftp.RemoveDirectory; FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); response.Close(); } catch (Exception ex) { Console.WriteLine("刪除目錄出錯:" + ex.Message); } } /// <summary> /// 從ftp服務器上得到文件夾列表 /// </summary> /// <param name="RequedstPath">服務器下的相對路徑</param> /// <returns></returns> public static List<string> GetDirctory(string RequedstPath) { List<string> strs = new List<string>(); try { string uri = path + RequedstPath; //目標路徑 path爲服務器地址 FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); // ftp用戶名和密碼 reqFTP.Credentials = new NetworkCredential(username, password); reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails; WebResponse response = reqFTP.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream());//中文文件名 string line = reader.ReadLine(); while (line != null) { if (line.Contains("<DIR>")) { string msg = line.Substring(line.LastIndexOf("<DIR>") + 5).Trim(); strs.Add(msg); } line = reader.ReadLine(); } reader.Close(); response.Close(); return strs; } catch (Exception ex) { Console.WriteLine("獲取目錄出錯:" + ex.Message); } return strs; } /// <summary> /// 從ftp服務器上得到文件列表 /// </summary> /// <param name="RequedstPath">服務器下的相對路徑</param> /// <returns></returns> public static List<string> GetFile(string RequedstPath) { List<string> strs = new List<string>(); try { string uri = path + RequedstPath; //目標路徑 path爲服務器地址 FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); // ftp用戶名和密碼 reqFTP.Credentials = new NetworkCredential(username, password); reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails; WebResponse response = reqFTP.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream());//中文文件名 string line = reader.ReadLine(); while (line != null) { if (!line.Contains("<DIR>")) { string msg = line.Substring(39).Trim(); strs.Add(msg); } line = reader.ReadLine(); } reader.Close(); response.Close(); return strs; } catch (Exception ex) { Console.WriteLine("獲取文件出錯:" + ex.Message); } return strs; } }
下面建立一個WindowsForm項目:MyWatcherweb
添加一個配置文件:數據庫
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="conn" connectionString="Data Source=;Initial Catalog=;User ID=;Password=;" providerName="System.Data.SqlClient"/> </connectionStrings> <appSettings> <add key="WatchPath" value="E:\"/> <add key="WatchType" value="*.jpg"/> <add key="Line" value="Default"/> <add key="Station" value="Default"/> <add key="Employee" value="Default"/> <add key="ServerIp" value=""/> <add key="Username" value=""/> <add key="Password" value=""/> </appSettings> </configuration>
使用FileSystemWatcher進行文件監聽和處理時要注意,OnCreate事件是文件剛建立的時候就觸發,此時文件還未完成寫操做,文件也不是一個完整的文件。因此,在下面的代碼中,將文件的監聽和上傳分開去作,並經過一個字典做爲中間的媒介。服務器
注意:在一個監聽的目錄下面,文件名相同的,默認視爲相同的文件,即便它們的子目錄不一樣,在字典中的鍵是同樣的。app
下面是監聽程序的代碼框架:框架
using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Threading; using System.Windows.Forms; namespace MyWatch { public partial class MyForm : Form { public MyForm() { InitializeComponent(); } //建立一個字典,記錄最新建立的圖片 private Dictionary<string, string> _fileList = new Dictionary<string, string>(); //監聽目錄 private string _watchPath = ConfigurationManager.AppSettings["WatchPath"]; //監聽類型 private string _watchType = ConfigurationManager.AppSettings["WatchType"]; //監聽線程 private Thread thread; private void MyForm_Load(object sender, EventArgs e) { FileSystemWatcher myWather = new FileSystemWatcher(_watchPath, _watchType); myWather.IncludeSubdirectories = true; myWather.Created += new FileSystemEventHandler(OnCreated);//建立 myWather.Changed += new FileSystemEventHandler(OnChanged);//更改 myWather.EnableRaisingEvents = true; thread = new Thread(SaveFile); thread.Start(); } //監聽事件 private void OnCreated(object source, FileSystemEventArgs e) { WatchProcess(e); } private void OnChanged(object source, FileSystemEventArgs e) { WatchProcess(e); } //監聽處理:在文件建立或更改時,將<圖片名稱,圖片地址>保存到字典中 private void WatchProcess(FileSystemEventArgs e) { } //上傳圖片 private void SaveFile() { while (true) { } } } }
下面的是監聽到文件建立時的處理:ide
//監聽處理:在文件建立或更改時,將<圖片名稱,圖片地址>保存到字典中 private void WatchProcess(FileSystemEventArgs e) { string[] pathArr = e.FullPath.Split('\\'); if (pathArr.Length > 1) { //文件更改時產生的系統文件會以$開頭 string fileName = pathArr[pathArr.Length - 1].ToUpper().Trim(); if (fileName.ToCharArray()[0] == '$') return; //進行數據更新 lock (_fileList) { _fileList[fileName] = e.FullPath; } } }
使用線程上傳圖片:ui
//上傳圖片 private void SaveFile() { while (true) { //獲取當前保存在字典中的文件數量,而後給個等待時間,讓文件建立結束 int count = _fileList.Count; Thread.Sleep(10 * 1000); //保存上傳過的EL圖片文件名,用於從字典中刪除上傳過的圖片 List<string> stringKeys = new List<string>(); //參數 string strDate = DateTime.Now.ToString("yyyyMMdd"); string strLine = ConfigurationManager.AppSettings["Line"]; string strStation = ConfigurationManager.AppSettings["Station"]; string strEmployee = ConfigurationManager.AppSettings["Employee"]; //使用緩衝過的數據量進行操做 for (int i = 0; i < count; i++) { //文件被刪除就不處理 if (!File.Exists(_fileList.ElementAt(i).Value)) continue; string[] fi = _fileList.ElementAt(i).Key.Split('.'); if (fi.Length != 2) continue; //隱藏文件不處理 FileInfo fileInfo = new FileInfo(_fileList.ElementAt(i).Value); if ((fileInfo.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden) { try { //獲取服務器目錄:日期 List<string> pathDate = FtpHelper.GetDirctory(""); if (!pathDate.Contains(strDate)) FtpHelper.MakeDir(strDate); //獲取服務器目錄:線別 List<string> pathLine = FtpHelper.GetDirctory("/" + strDate); if (!pathLine.Contains(strLine)) FtpHelper.MakeDir(strDate + "/" + strLine); //獲取服務目錄:工位 List<string> pathStation = FtpHelper.GetDirctory("/" + strDate + "/" + strLine); if (!pathStation.Contains(strStation)) FtpHelper.MakeDir(strDate + "/" + strLine + "/" + strStation); //若是文件名存在,則建立一個帶時間後綴的文件 string objPath = strDate + "/" + strLine + "/" + strStation; string fName = _fileList.ElementAt(i).Key; if (FtpHelper.GetFileSize(objPath + "/" + fName) > -1) fName = fi[0] + "_" + DateTime.Now.ToString("HHmmss") + "." + fi[1]; //上傳 FtpHelper.FileUpLoad(_fileList.ElementAt(i).Value, fName, objPath); //數據庫操做 //此處省略 } catch { } } //保存這個鍵,用於從Dictionary中刪除上傳過的EL,不能在for循環中進行刪除,會致使長度不一致 stringKeys.Add(_fileList.ElementAt(i).Key); } //從Dictionary中移除添 lock (_fileList) { foreach (var i in stringKeys) { _fileList.Remove(i); } } } }
源碼下載url
參考:spa
http://wenku.baidu.com/link?url=oM5DGnopZkeLxGopJZP7EypkO-X-sTeoXTxX9lCkMqiAoXzrJPaSrxKDd5Qz12hM5tbuixHOi-QgK6GaQYvS_PkR8Y7YUVJWSB6sGShXEie
http://www.cnblogs.com/rond/archive/2012/07/30/2611295.html
http://www.cnblogs.com/zhaojingjing/archive/2011/01/21/1941586.html
附:ftp添加有問題,會致使530錯誤