Browse Source

更新阿里云 文件上传,调整为 异步分片上传!

样式分支
fyf 2 years ago
parent
commit
2e8655c299
4 changed files with 251 additions and 42 deletions
  1. +5
    -0
      BPASmartClient.IoT/BPASmartClient.IoT.csproj
  2. +4
    -12
      BPASmartClient.IoT/DataVClient.cs
  3. +90
    -30
      BPASmartClient.IoT/Model/FileUpload.cs
  4. +152
    -0
      BPASmartClient.IoT/Model/Sample.cs

+ 5
- 0
BPASmartClient.IoT/BPASmartClient.IoT.csproj View File

@@ -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>


+ 4
- 12
BPASmartClient.IoT/DataVClient.cs View File

@@ -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
{


+ 90
- 30
BPASmartClient.IoT/Model/FileUpload.cs View File

@@ -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));


+ 152
- 0
BPASmartClient.IoT/Model/Sample.cs View File

@@ -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; }
}
}

Loading…
Cancel
Save