@@ -5,10 +5,15 @@ | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="AlibabaCloud.OpenApiClient" Version="0.1.3" /> | |||
<PackageReference Include="AlibabaCloud.SDK.Iot20180120" Version="3.0.5" /> | |||
<PackageReference Include="AlibabaCloud.TeaConsole" Version="0.1.0" /> | |||
<PackageReference Include="AlibabaCloud.TeaUtil" Version="0.1.13" /> | |||
<PackageReference Include="Aliyun.OSS.SDK" Version="2.13.0" /> | |||
<PackageReference Include="M2Mqtt" Version="4.3.0" /> | |||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | |||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" /> | |||
<PackageReference Include="Tea" Version="1.0.11" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
@@ -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<FileUploadModelResult>(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 | |||
{ | |||
@@ -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 | |||
/// </summary> | |||
public class FileUpload | |||
{ | |||
public static Dictionary<string, string> UploadData = new Dictionary<string, string>(); | |||
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; | |||
/// <summary> | |||
/// 一次性上传的包 | |||
/// </summary> | |||
public static byte[] FileBlock; | |||
/// <summary> | |||
/// 请求反馈信息 | |||
/// </summary> | |||
public static FileUploadModelResult modelResult=null; | |||
/// <summary> | |||
/// 文件请求上传 | |||
/// </summary> | |||
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<QueryDeviceFileResponseBodyData> 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<string, string> { {"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<string, string> { {"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); | |||
} | |||
/// <summary> | |||
/// 文件上传 | |||
/// </summary> | |||
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)); | |||
@@ -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<QueryDeviceFileResponseBodyData> FileQueryALL(string DeviceName) | |||
{ | |||
List<QueryDeviceFileResponseBodyData> retdata = new List<QueryDeviceFileResponseBodyData>(); | |||
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<AlibabaCloudRes>(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; | |||
} | |||
/// <summary> | |||
/// 替换字符串起始位置(开头)中指定的字符串 | |||
/// </summary> | |||
/// <param name="s">源串</param> | |||
/// <param name="searchStr">查找的串</param> | |||
/// <param name="replaceStr">替换的目标串</param> | |||
/// <returns></returns> | |||
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<summary> 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; } | |||
} | |||
} |