From 2e8655c299a7c7ffd195eb04fe15ec76e4e2ed27 Mon Sep 17 00:00:00 2001 From: fyf Date: Thu, 26 May 2022 10:28:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=98=BF=E9=87=8C=E4=BA=91?= =?UTF-8?q?=20=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=EF=BC=8C=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E4=B8=BA=20=E5=BC=82=E6=AD=A5=E5=88=86=E7=89=87?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BPASmartClient.IoT/BPASmartClient.IoT.csproj | 5 + BPASmartClient.IoT/DataVClient.cs | 16 +- BPASmartClient.IoT/Model/FileUpload.cs | 120 +++++++++++---- BPASmartClient.IoT/Model/Sample.cs | 152 +++++++++++++++++++ 4 files changed, 251 insertions(+), 42 deletions(-) create mode 100644 BPASmartClient.IoT/Model/Sample.cs diff --git a/BPASmartClient.IoT/BPASmartClient.IoT.csproj b/BPASmartClient.IoT/BPASmartClient.IoT.csproj index 0f2a2042..ac372833 100644 --- a/BPASmartClient.IoT/BPASmartClient.IoT.csproj +++ b/BPASmartClient.IoT/BPASmartClient.IoT.csproj @@ -5,10 +5,15 @@ + + + + + diff --git a/BPASmartClient.IoT/DataVClient.cs b/BPASmartClient.IoT/DataVClient.cs index 4a120b24..f2bf1c2a 100644 --- a/BPASmartClient.IoT/DataVClient.cs +++ b/BPASmartClient.IoT/DataVClient.cs @@ -298,25 +298,17 @@ namespace BPASmartClient.IoT { string FileName = result.data?.fileName; string uploadId = result.data?.uploadId; - FileUpload.SetUploadData(result.id,uploadId); - FileUpload.FileSend(DeviceDataV, uploadId); - MessageLog.GetInstance.Show($"请求上传【阿里云】成功,准备上传日志文件【HBL.LogDir{DateTime.Now.ToString("yyyy_M_d")}.log】"); + FileUpload.FileSend(DeviceDataV, uploadId, result.data.offset); + MessageLog.GetInstance.Show($"[阿里云上传]:请求上传云回执成功."); } else - MessageLog.GetInstance.Show($"【HBL.LogDir{DateTime.Now.ToString("yyyy_M_d")}.log】请求上传【阿里云】失败,{result.message}"); + MessageLog.GetInstance.Show($"[阿里云上传]:请求上传云回执失败.原因:{result.message}"); } else if (DeviceDataV.FileUpLoadSendReplyTopic == topic)//文件上传Topic { FileUploadModelResult result = Tools.JsonToObjectTools(message); - if (result.code == 200) - { - MessageLog.GetInstance.Show($"今日日志文件“HBL.LogDir{DateTime.Now.ToString("yyyy_M_d")}.log”更新上传【阿里云】成功"); - bool complete = result.data.complete; - string uploadId = result.data?.uploadId; - }else - MessageLog.GetInstance.Show($"今日日志文件“HBL.LogDir{DateTime.Now.ToString("yyyy_M_d")}.log”更新上传【阿里云】失败,{result.message}"); - + FileUpload.modelResult = result; } else if (DeviceDataV.CancelFileUpLoadSendReplyTopic == topic)//取消文件上传Topic { diff --git a/BPASmartClient.IoT/Model/FileUpload.cs b/BPASmartClient.IoT/Model/FileUpload.cs index 45021c59..ff5fbe5b 100644 --- a/BPASmartClient.IoT/Model/FileUpload.cs +++ b/BPASmartClient.IoT/Model/FileUpload.cs @@ -1,4 +1,5 @@ using BPASmartClient.Helper; +using BPASmartClient.Message; using BPASmartDatavDeviceClient.IoT; using DataVAPI.Tool.IOT; using System; @@ -6,7 +7,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; +using static AlibabaCloud.SDK.Iot20180120.Models.QueryDeviceFileResponseBody; namespace BPASmartClient.IoT.Model { @@ -15,55 +18,112 @@ namespace BPASmartClient.IoT.Model /// public class FileUpload { - public static Dictionary UploadData = new Dictionary(); public static string FileName = $"HBL.LogDir{DateTime.Now.ToString("yyyy_M_d")}"; public static string path = $"{System.AppDomain.CurrentDomain.BaseDirectory}LogDir\\{FileName}.log"; - public static void SetUploadData(string key, string value) - { - UploadData[key] = value; - } - public static string GetUploadData(string key) - { - return UploadData.ContainsKey(key) ? UploadData[key] : string.Empty; - } - public static long length = 0; + /// + /// 一次性上传的包 + /// public static byte[] FileBlock; /// + /// 请求反馈信息 + /// + public static FileUploadModelResult modelResult=null; + /// /// 文件请求上传 /// public static void FileRequest(DataVReport dataV) { - FileBlock = FileContent(path); - length = FileBlock.Count(); - FileUploadModel fileUpload = new FileUploadModel(); - fileUpload.@params.fileName = FileName; - fileUpload.@params.fileSize = length; - fileUpload.@params.conflictStrategy = "overwrite";//覆盖模式 - //fileUpload.@params.ficMode = "crc64"; - //fileUpload.@params.ficValue = CRC.ToCRC16(FileBlock); - fileUpload.@params.initUid = $"ab{RandomHelper.GenerateRandomCode()}"; + ThreadManage.GetInstance().Start(new Action(() => + { + try + { + List queryDeviceFiles= Sample.FileQueryALL(DataVClient.GetInstance().DeviceName); + QueryDeviceFileResponseBodyData _data= queryDeviceFiles?.Find(par => par.Name == FileName); + if (_data != null)//删除文件 + { + MessageLog.GetInstance.Show("阿里云设备下文件已存在,准备删除续传..."); + Sample.DeleteFile(DataVClient.GetInstance().DeviceName, _data.FileId); + MessageLog.GetInstance.Show("删除成功.准备上传.."); + } + byte[] FileBlockALL = FileContent(path); + //分包上传 + int length = FileBlockALL.Count(); + int bfb = (FileBlockALL.Count() / 130000) + 1; + MessageLog.GetInstance.Show($"[阿里云上传]:文件整理中总长度[{length}]字节,分包数[{bfb}]包."); + //分包上传 + for (int i = 0; i < bfb; i++) + { + modelResult = null; + byte[] data; + if (i == bfb - 1) data = new byte[FileBlockALL.Count() - i * 130000];//最后一包 + else data = new byte[130000];//前面的包 - //上传到阿里云物联网平台的OSS存储空间中 - fileUpload.@params.extraParams.ossOwnerType = "iot-platform"; + for (int k = 0; k < data.Length; k++) + { + data[k] = FileBlockALL[k + i * 130000]; + } + FileBlock = data; - //表示上传到设备所属用户自己的OSS存储空间中 - //{ossbucket}/aliyun-iot-device-file/${instanceId}/${productKey}/${serviceId}/${deviceName}/${fileName} - //fileUpload.@params.extraParams.ossOwnerType = "device-user"; - //fileUpload.@params.extraParams.serviceId = "black"; - //fileUpload.@params.extraParams.fileTag = new Dictionary { {"Time", DateTime.Now.ToString("yyyy_M_d") },{"Name", "HBL.LogDir" } }; + FileUploadModel fileUpload = new FileUploadModel(); + fileUpload.@params.fileName = FileName; + fileUpload.@params.fileSize =-1; - dataV.IOT_Publish(dataV.FileUpLoadTopic, Tools.JsonConvertTools(fileUpload)); + fileUpload.@params.conflictStrategy = length>130000 ? "append":"overwrite"; + //fileUpload.@params.conflictStrategy = "append";// "overwrite";//覆盖模式 + //fileUpload.@params.ficMode = "crc64"; + //fileUpload.@params.ficValue = CRC.ToCRC16(FileBlock); + fileUpload.@params.initUid = $"ab{RandomHelper.GenerateRandomCode()}"; + + //上传到阿里云物联网平台的OSS存储空间中 + fileUpload.@params.extraParams.ossOwnerType = "iot-platform"; + + //表示上传到设备所属用户自己的OSS存储空间中 + //{ossbucket}/aliyun-iot-device-file/${instanceId}/${productKey}/${serviceId}/${deviceName}/${fileName} + //fileUpload.@params.extraParams.ossOwnerType = "device-user"; + //fileUpload.@params.extraParams.serviceId = "black"; + //fileUpload.@params.extraParams.fileTag = new Dictionary { {"Time", DateTime.Now.ToString("yyyy_M_d") },{"Name", "HBL.LogDir" } }; + + dataV.IOT_Publish(dataV.FileUpLoadTopic, Tools.JsonConvertTools(fileUpload)); + MessageLog.GetInstance.Show($"[阿里云上传]:第[{i+1}]包数据,请求上传."); + + int count = 0; + while (modelResult == null)//等待上传完成 + { + if (count > 5) + { + MessageLog.GetInstance.Show($"[阿里云上传]:超时上传、未知原因、退出线程."); + + return; + } + Thread.Sleep(3000); count++; + } + + ; + + if(modelResult.code==200) + MessageLog.GetInstance.Show($"[阿里云上传]:第[{i + 1}]包,上传成功."); + else + MessageLog.GetInstance.Show($"[阿里云上传]:第[{i + 1}]包,上传失败.原因:{modelResult.message}"); + ; + } + } + catch (Exception ex) + { + MessageLog.GetInstance.ShowEx(ex.ToString()); + } + }), "文件请求上传", false); } /// /// 文件上传 /// - public static void FileSend(DataVReport dataV, string uploadId) + public static void FileSend(DataVReport dataV, string uploadId,long offset) { FileSendModel fileSend = new FileSendModel(); fileSend.@params.uploadId = uploadId; - fileSend.@params.offset = 0; - fileSend.@params.bSize = length; + fileSend.@params.offset = offset; + fileSend.@params.bSize = FileBlock.Count(); + fileSend.@params.isComplete = FileBlock.Count()==130000?false:true; //结构如下图 //Header.length(高 低) + Header(字节数组UTF-8) + 文件分片的字节数组 + "分片校验值CrC16 低 高" byte[] Header = Encoding.UTF8.GetBytes(Tools.JsonConvertTools(fileSend)); diff --git a/BPASmartClient.IoT/Model/Sample.cs b/BPASmartClient.IoT/Model/Sample.cs new file mode 100644 index 00000000..2c06ca98 --- /dev/null +++ b/BPASmartClient.IoT/Model/Sample.cs @@ -0,0 +1,152 @@ +using DataVAPI.Tool.IOT; +using System; +using System.Collections.Generic; +using Tea; +using static AlibabaCloud.SDK.Iot20180120.Models.QueryDeviceFileResponseBody; + + +namespace BPASmartClient.IoT.Model +{ + public class Sample + { + + /** + * 使用AK&SK初始化账号Client + * @param accessKeyId + * @param accessKeySecret + * @return Client + * @throws Exception + */ + public static AlibabaCloud.SDK.Iot20180120.Client CreateClient(string accessKeyId, string accessKeySecret) + { + AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config + { + // 您的AccessKey ID + AccessKeyId = accessKeyId, + // 您的AccessKey Secret + AccessKeySecret = accessKeySecret, + }; + // 访问的域名 + config.Endpoint = "iot.cn-shanghai.aliyuncs.com"; + return new AlibabaCloud.SDK.Iot20180120.Client(config); + } + + public static List FileQueryALL(string DeviceName) + { + List retdata = new List(); + AlibabaCloud.SDK.Iot20180120.Client client = CreateClient("LTAI5tDbUDuCvqU5hP8ZpHHV", "SvNIRQuz3BQFEaC3PFSJdgpeOKWFRi"); + AlibabaCloud.SDK.Iot20180120.Models.QueryDeviceFileListRequest queryDeviceFileListRequest = new AlibabaCloud.SDK.Iot20180120.Models.QueryDeviceFileListRequest + { + IotInstanceId = "iot-06z00g9pf3kwtxp", + DeviceName = DataVClient.GetInstance().DeviceName, + ProductKey = DataVClient.GetInstance().ProductKey, + }; + AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); + AlibabaCloud.SDK.Iot20180120.Models.QueryDeviceFileListResponse resp = client.QueryDeviceFileListWithOptions(queryDeviceFileListRequest, runtime); + + AlibabaCloudRes cloudRes = Tools.JsonToObjectTools(AlibabaCloud.TeaUtil.Common.ToJSONString(resp.ToMap())); + cloudRes?.body?.Data?.FileSummary?.ForEach(fileSummary => + { + QueryDeviceFileResponseBodyData _data = FileQuery(DeviceName, fileSummary.FileId); + if (_data != null) + { + _data.UtcCreatedOn = DateTime.Parse(_data.UtcCreatedOn).AddHours(8).ToString("yyyy-MM-dd HH:mm:ss"); + _data.DownloadUrl = _data.DownloadUrl.Replace("http://", "https://"); + retdata.Add(_data); + } + }); + return retdata; + } + /// + /// 替换字符串起始位置(开头)中指定的字符串 + /// + /// 源串 + /// 查找的串 + /// 替换的目标串 + /// + public static string CutStarStr(string s, string searchStr, string replaceStr) + { + var result = s; + try + { + if (string.IsNullOrEmpty(result)) + { + return result; + } + if (s.Length < searchStr.Length) + { + return result; + } + if (s.IndexOf(searchStr, 0, searchStr.Length, StringComparison.Ordinal) > -1) + { + result = s.Substring(searchStr.Length); + } + return result; + } + catch (Exception e) + { + return result; + } + } + public static QueryDeviceFileResponseBodyData FileQuery(string DeviceName, string FileId) + { + AlibabaCloud.SDK.Iot20180120.Client client = CreateClient("LTAI5tDbUDuCvqU5hP8ZpHHV", "SvNIRQuz3BQFEaC3PFSJdgpeOKWFRi"); + AlibabaCloud.SDK.Iot20180120.Models.QueryDeviceFileRequest queryDeviceFileRequest = new AlibabaCloud.SDK.Iot20180120.Models.QueryDeviceFileRequest + { + IotInstanceId = "iot-06z00g9pf3kwtxp", + DeviceName = DataVClient.GetInstance().DeviceName, + ProductKey = DataVClient.GetInstance().ProductKey, + FileId = FileId, + }; + AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); + // 复制代码运行请自行打印 API 的返回值 + QueryDeviceFileResponseBodyData queryDeviceFile = client.QueryDeviceFileWithOptions(queryDeviceFileRequest, runtime).Body.Data; + return queryDeviceFile; + } + + public static bool? DeleteFile(string DeviceName, string FileId) + { + AlibabaCloud.SDK.Iot20180120.Client client = CreateClient("LTAI5tDbUDuCvqU5hP8ZpHHV", "SvNIRQuz3BQFEaC3PFSJdgpeOKWFRi"); + AlibabaCloud.SDK.Iot20180120.Models.DeleteDeviceFileRequest deleteDeviceFileRequest = new AlibabaCloud.SDK.Iot20180120.Models.DeleteDeviceFileRequest + { + IotInstanceId = "iot-06z00g9pf3kwtxp", + DeviceName = DataVClient.GetInstance().DeviceName, + ProductKey = DataVClient.GetInstance().ProductKey, + FileId = FileId, + }; + AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); + // 复制代码运行请自行打印 API 的返回值 + return client.DeleteDeviceFileWithOptions(deleteDeviceFileRequest, runtime).Body.Success; + } + + } + + public class AlibabaCloudRes + { + public object headers { get; set; } + public StrRes body { get; set; } + } + public class StrRes + { + public string code { get; set; } + public string CurrentPage { get; set; } + public ResData Data { get; set; } + public string ErrorMessage { get; set; } + public int PageCount { get; set; } + public int PageSize { get; set; } + public string RequestId { get; set; } + public bool Success { get; set; } + public int Total { get; set; } + } + public class ResData + { + public List FileSummary { get; set; } + } + public class summary + { + public string UtcCreatedOn { get; set; } + public string Size { get; set; } + public string FileId { get; set; } + public string Name { get; set; } + } +}