using com.hnshituo.core.webapp.vo; using ServiceStack.Redis; using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; namespace CarLocalMeter { public class ImageOption { Log lg = Log.GetInstance(); Thread task; string sPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "imgShort\\"; /// /// 启动TFP上传线程 /// public void Start() { if (task == null) { task = new Thread(new ThreadStart(Doworks)); task.Start(); } } public void Stop() { if (task != null) { task.Abort(); task = null; } } private void Doworks() { do { //能ping通服务器IP的情况下 if (CacleCls.serverFlag) { int waitSecs = 10000; try { //每隔10秒传一次计量图片信息 UploadFiles(GetFiles(sPath + "formalImg", ".jpg")); } catch (Exception exp) { lg.WriteLog(LogType.SystemLog, $"图片压缩上传线程异常:{exp.Message}"); } finally { Thread.Sleep(waitSecs); } } } while (true); } public void ZipFiles() { try { string oldTempImgId = CacleCls.tempNo, oldActualFirstNo = CacleCls.actualNo; ArrayList UnzipedFiles = GetFiles(sPath + "formalImg", ".jpg");//tmp! if (UnzipedFiles == null || UnzipedFiles.Count == 0) return; foreach (string fn in UnzipedFiles) { if (string.IsNullOrEmpty(fn)) continue; if (!File.Exists(fn)) continue; //如果带tempImg则说明没有压缩过,需要压缩 if (fn.Contains("tempImg") && fn.Contains(oldTempImgId)) { //临时目录图片压缩后存储到正式目录 string jpgFile = fn.Replace("_tempImg", "").Replace(oldTempImgId, oldActualFirstNo); Image img = ImageZip.BytesToBitmap(ImageZip.ZipImageByte(fn)); if (fn.Contains("_2.jpg")) //fn.Contains("_1.jpg") || { ImageZip.CompressionImage(img, jpgFile, AppConfigCache.imgMass > 100 ? 100 : AppConfigCache.imgMass); } else { ImageZip.CompressionImage(img, jpgFile, AppConfigCache.imgMass2 > 100 ? 100 : AppConfigCache.imgMass2); } File.Delete(fn);//删除临时目录数据 } } } catch (Exception ex) { lg.WriteLog(LogType.SystemLog, $"图片压缩异常:{ex.Message}"); } } /// /// actualNos的key为本地计量编号,value为服务端一次计量编号 /// 也就是说在数据进行结净的时候,需返回2个一次计量编号以及传过去取的老计量编号 /// /// public void ZipFiles(Dictionary actualNos) { try { ArrayList UnzipedFiles = GetFiles(sPath + "formalImg", ".jpg");//tmp! if (UnzipedFiles == null || UnzipedFiles.Count == 0) return; bool flag = false; string jpgFile = ""; foreach (string fn in UnzipedFiles) { if (string.IsNullOrEmpty(fn)) continue; if (!File.Exists(fn)) continue; //如果带tempImg则说明没有压缩过,需要压缩 if (fn.Contains("_tempImg")) { flag = false; jpgFile = fn.Replace("_tempImg", ""); foreach (KeyValuePair kvp in actualNos) { if (fn.Contains(kvp.Key)) { jpgFile = jpgFile.Replace(kvp.Key, kvp.Value); flag = true; break; } } if (flag) { Image img = ImageZip.BytesToBitmap(ImageZip.ZipImageByte(fn)); if (fn.Contains("_2.jpg")) //fn.Contains("_1.jpg") || { ImageZip.CompressionImage(img, jpgFile.Replace("tempImg", "formalImg"), AppConfigCache.imgMass > 100 ? 100 : AppConfigCache.imgMass); } else { ImageZip.CompressionImage(img, jpgFile.Replace("tempImg", "formalImg"), AppConfigCache.imgMass2 > 100 ? 100 : AppConfigCache.imgMass2); } File.Delete(fn);//删除临时目录数据 } /* //这里有个问题在于,假如网络正常的时候正好过磅了,可能导致过磅图片也被移送到bakImg,所以这里需在计量未锁定(车以下磅,且名称与计量的图片编号不一致的时候,移送) else if (!fn.Contains(CacleCls.tempNo) && !CacleCls.isLock) { //将文件移送到bakImg文件夹 File.Move(fn, fn.Replace("tempImg", "bakImg")); } //*/ } } } catch (Exception ex) { lg.WriteLog(LogType.SystemLog, $"图片压缩异常:{ex.Message}"); } } public ArrayList GetFiles(string _dirPath, string extensionName) { ArrayList files = new ArrayList(); if (!Directory.Exists(_dirPath)) return null; DirectoryInfo theFolder = new DirectoryInfo(_dirPath); FileInfo[] fileinfos = theFolder.GetFiles("*" + extensionName); if (fileinfos != null && fileinfos.Count() > 0) { foreach (FileInfo fi in fileinfos) { if (fi.CreationTime.AddHours(AppConfigCache.imgTimeOut) < DateTime.Now && fi.Name.Contains("tempImg")) { //如果5分钟了还没上传,则认为不需要上传了 fi.MoveTo(fi.FullName.Replace("formalImg", "bakImg")); } else { files.Add(fi.FullName); } } } DirectoryInfo[] dirInfos = theFolder.GetDirectories();//返回当前目录的子目录 if (dirInfos != null && dirInfos.Count() > 0) { foreach (DirectoryInfo di in dirInfos) { files.AddRange(GetFiles(di.FullName, extensionName)); } } return files; } // 后台刷FTP线程调用 private void UploadFiles(ArrayList files) { string localpath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, @"imgShort\formalImg\")); foreach (string _filepath in files) { try { // 临时文件不上传 if (!_filepath.Contains("_temp")) { string ftpdir = Path.Combine(AppConfigCache.fpath, DateTime.Now.ToString("yyyy-MM-dd")); //验证文件名是否合法 string filename = Path.GetFileName(_filepath); //filename : 计量作业编号_序号.jpg 计量作业编号:计量点编号+年月日时分秒 MeterWorkImage ci = ParseFileName(filename, ftpdir.Replace("upload", "download")); if (ci == null) continue; // 上传文件 UploadRequest(ftpdir, localpath + filename); //存储计量数据的时候,实际上是先将计量数据及图片路径 MeterWorkImageService service = new MeterWorkImageService(); RESTfulResult rm = service.doSaveWf(ci); //db.doOption("MeterWorkImageService", "doSaveWf", new object[] { ci }, 1); if (rm.Succeed) { WriteLog(string.Format("更新图片记录[{0}]:{1}", ci.actualFirstNo, filename)); File.Delete(_filepath); } else { WriteLog(string.Format("上传图片失败! [{0}]\n{1}", ci.actualFirstNo, filename)); } // } } catch (Exception exp) { WriteLog(string.Format("上传图片失败! [{0}]\n{1}", _filepath, exp.Message)); } } } private void RemoveRedundantDir(string _path, int deep) { DirectoryInfo theFolder = new DirectoryInfo(_path); DirectoryInfo[] dirInfos = theFolder.GetDirectories(); if (dirInfos != null && dirInfos.Count() > 0) { foreach (DirectoryInfo di in dirInfos) { RemoveRedundantDir(di.FullName, deep + 1); } } try { if (deep == 0) return; FileInfo[] fileinfos = theFolder.GetFiles(); if (fileinfos == null || fileinfos.Count() == 0) { DateTime dt; if (DateTime.TryParseExact(theFolder.Name, "yyyy-MM-dd", CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces, out dt)) { if (TimeSpan.FromTicks(DateTime.Today.Ticks).Subtract(TimeSpan.FromTicks(dt.Date.Ticks)).TotalDays > 1) { Directory.Delete(_path); } } } } catch { } } /// /// 验证图片名称 /// /// 计量点编号_作业编号_序号.jpg /// /// private MeterWorkImage ParseFileName(string filename, string ftpdir) { MeterWorkImage ci = new MeterWorkImage(); filename = Path.GetFileName(filename); string[] segs = filename.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries); if (segs == null || segs.Count() < 3) { WriteLog("文件名不符合要求! (3段命名):" + filename); return null; } int seq; //int icar_seq = 0; //int.TryParse(car_seq, out icar_seq); string[] seqs = segs[2].Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); if (seqs == null || seqs.Count() == 0 || !int.TryParse(seqs[0], out seq)) { WriteLog("文件名不符合要求! (序号不正确):" + filename); return null; } string fullfilename = ftpdir + "/" + filename; if (fullfilename.Substring(0, 8) == "https://") { fullfilename = fullfilename.Substring(0, 8) + fullfilename.Substring(8).Replace("//", "/").Replace("//", "/"); } else if (fullfilename.Substring(0, 7) == "http://") { fullfilename = fullfilename.Substring(0, 7) + fullfilename.Substring(7).Replace("//", "/").Replace("//", "/"); } else { fullfilename = fullfilename.Replace("//", "/").Replace("//", "/"); } PropertyInfo pi = null; try { pi = ci.GetType().GetProperty(string.Format("imageFile{0}", seq)); pi.SetValue(ci, fullfilename.Replace("/pub", "")); } catch { WriteLog("文件名不符合要求! (序号超出数据库要求):" + fullfilename); return null; } //ci.image_time = DateTime.ParseExact(segs[0].Substring(segs[0].Length - 14, 14), "yyyyMMddHHmmss", CultureInfo.CurrentCulture); ci.actualFirstNo = segs[1]; return ci; } private static void WriteLog(string str) { // 20220925 By BourneCao 暂时屏蔽语音播放日志 return; try { string m_szRunPath; m_szRunPath = System.Environment.CurrentDirectory; if (System.IO.Directory.Exists(m_szRunPath + "\\log") == false) { System.IO.Directory.CreateDirectory(m_szRunPath + "\\log"); } string strDate = System.DateTime.Now.ToString("yyyyMMdd"); string strPathFile = m_szRunPath + "\\log\\" + strDate; if (!Directory.Exists(strPathFile))//如果不存在就创建file文件夹 { Directory.CreateDirectory(strPathFile); } System.IO.TextWriter tw = new System.IO.StreamWriter(strPathFile + "\\FTP_image_" + strDate + ".log", true); tw.WriteLine(System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); tw.WriteLine(str); tw.WriteLine("\r\n"); tw.Close(); } catch { } } private void UploadRequest(string url, string filePath) { // 时间戳,用做boundary string timeStamp = DateTime.Now.Ticks.ToString("x"); //根据uri创建HttpWebRequest对象 HttpWebRequest oWebrequest = (HttpWebRequest)WebRequest.Create(new Uri(url)); //如果是发送HTTPS请求 if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | (SecurityProtocolType)0x300 //Tls11 | (SecurityProtocolType)0xC00; //Tls12 oWebrequest = WebRequest.Create(url) as HttpWebRequest; oWebrequest.ProtocolVersion = HttpVersion.Version11; } else { oWebrequest = WebRequest.Create(url) as HttpWebRequest; } //HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(new Uri(url)); oWebrequest.Method = "POST"; oWebrequest.AllowWriteStreamBuffering = false; //对发送的数据不使用缓存 oWebrequest.Timeout = 300000; //设置获得响应的超时时间(300秒) oWebrequest.ContentType = "multipart/form-data; boundary=" + timeStamp; //文件 FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); BinaryReader binaryReader = new BinaryReader(fileStream); //头信息 string boundary = "--" + timeStamp; string dataFormat = boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\nContent-Type:application/octet-stream\r\n\r\n"; string header = string.Format(dataFormat, "file", Path.GetFileName(filePath)); byte[] postHeaderBytes = Encoding.UTF8.GetBytes(header); //结束边界 byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + timeStamp + "--\r\n"); long length = fileStream.Length + postHeaderBytes.Length + boundaryBytes.Length; oWebrequest.ContentLength = length;//请求内容长度 try { //每次上传4k int bufferLength = 4096; byte[] buffer = new byte[bufferLength]; //已上传的字节数 long offset = 0; int size = binaryReader.Read(buffer, 0, bufferLength); Stream postStream = oWebrequest.GetRequestStream(); //发送请求头部消息 postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length); while (size > 0) { postStream.Write(buffer, 0, size); offset += size; size = binaryReader.Read(buffer, 0, bufferLength); } //添加尾部边界 postStream.Write(boundaryBytes, 0, boundaryBytes.Length); postStream.Close(); //获取服务器端的响应 using (HttpWebResponse response = (HttpWebResponse)oWebrequest.GetResponse()) { Stream receiveStream = response.GetResponseStream(); StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8); string returnValue = readStream.ReadToEnd(); response.Close(); readStream.Close(); } } catch (Exception ex) { //Debug.WriteLine("文件传输异常: " + ex.Message); } finally { fileStream.Close(); binaryReader.Close(); } } private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; //总是接受 } } }