一个简单的图片监听和上传程序
在制造业的某些工艺中,可能会对产品进行拍照,这时需要监听图片文件并上传到服务器进行保存。一开始,想将图片的二进制数据转换成string类型,然后通过webservice上传,但是报错“HTTP 状态 400 失败: Bad Request”。毕竟,webservice使用的是HTTP协议,如果想传文件的话,有FTP协议干嘛不用。然后在网上找了个C#使用FTP的帮助类(有点改动):
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项目:MyWatcher
添加一个配置文件:
<?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事件是文件刚创建的时候就触发,此时文件还未完成写操作,文件也不是一个完整的文件。所以,在下面的代码中,将文件的监听和上传分开去做,并通过一个字典作为中间的媒介。
注意:在一个监听的目录下面,文件名相同的,默认视为相同的文件,即使它们的子目录不同,在字典中的键是一样的。
下面是监听程序的代码框架:
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) { } } } }
下面的是监听到文件创建时的处理:
//监听处理:在文件创建或更改时,将<图片名称,图片地址>保存到字典中 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; } } }
使用线程上传图片:
//上传图片 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); } } } }
参考:
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错误