一个简单的图片监听和上传程序

在制造业的某些工艺中,可能会对产品进行拍照,这时需要监听图片文件并上传到服务器进行保存。一开始,想将图片的二进制数据转换成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;
        }

    }
View Code

下面创建一个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错误

 

posted on 2015-01-15 12:33  凡一二三  阅读(3740)  评论(1编辑  收藏  举报