目录
问题
生产流水线使用线阵相机采集原始图像后,经过预处理后上传到服务器。图像处理完成后保存到本地磁盘,再从本地磁盘读取图像后调用http接口传到服务器,图像保存再读取存在两次IO操作,IO操作耗时较长是性能瓶颈,提高上传速度。
思路:图像处理完成不需要存盘直接上传。因此1.需要把图像转换为可以网络传输的数组;2.上传图像数据同时提交Form表单数据。
解决
1.使用 cv::imencode()函数 直接 将cv::Mat数据编码成字节数组。
2.使用WebClient将图像数组和表单数组拼接上传。
上传接口
此接口直接使用的本地文件转换成的字节数组,实际按照1中所介绍进行抓换,需要调用C++代码:
//上传请求
public static bool UploadFileByHttp2(string webUrl, string localFileName, string analyze)
{
try
{
// 检查文件是否存在
if (!File.Exists(localFileName))
{
//MessageBox.Show("{0} does not exist!", localFileName);
//testRate.Text = "localFile does not exist!";
return false;
}
string filedValue = "hello_world", responseText = "";
FileStream fs = new FileStream(localFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
byte[] fileBytes = new byte[fs.Length];
fs.Read(fileBytes, 0, fileBytes.Length);
fs.Close(); fs.Dispose();
HttpRequestClient httpRequestClient = new HttpRequestClient();
//httpRequestClient.SetFieldValue("key", filedValue);
httpRequestClient.SetFieldValue("key1", analyze);
httpRequestClient.SetFieldValue("key2", "232");
httpRequestClient.SetFieldValue("key3", "123");
httpRequestClient.SetFieldValue("key4", "kong");
httpRequestClient.SetFieldValue("key5", "out");
httpRequestClient.SetFieldValue("file", Path.GetFileName(localFileName), "image/jpeg", fileBytes);
httpRequestClient.Upload(webUrl, out responseText);
return true;
}
catch (Exception e)
{
Console.WriteLine("Exception caught: {0}", e);
return false;
}
}
上传类封装
需要自己拼接表单和图像数组:
/// 封装Http请求
/// description:http post请求客户端
public class HttpRequestClient
{
#region //字段
private ArrayList bytesArray;
private Encoding encoding = Encoding.UTF8;
private string boundary = String.Empty;
#endregion
#region //构造方法
public HttpRequestClient()
{
bytesArray = new ArrayList();
string flag = DateTime.Now.Ticks.ToString("x");
boundary = "---------------------------" + flag;
}
#endregion
#region //方法
/// <summary>
/// 合并请求数据
/// </summary>
/// <returns></returns>
private byte[] MergeContent()
{
int length = 0;
int readLength = 0;
string endBoundary = "--" + boundary + "--\r\n";
byte[] endBoundaryBytes = encoding.GetBytes(endBoundary);
bytesArray.Add(endBoundaryBytes);
foreach (byte[] b in bytesArray)
{
length += b.Length;
}
byte[] bytes = new byte[length];
foreach (byte[] b in bytesArray)
{
b.CopyTo(bytes, readLength);
readLength += b.Length;
}
return bytes;
}
/// <summary>
/// 上传
/// </summary>
/// <param name="requestUrl">请求url</param>
/// <param name="responseText">响应</param>
/// <returns></returns>
public bool Upload(String requestUrl, out String responseText)
{
WebClient webClient = new WebClient();
webClient.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
webClient.Headers.Add("Authorization", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOiIxNiIsImlzcyI6ImJhb2NoZW5neGluIiwiZXhwIjoxNTYwNTk0NTExLCJpYXQiOjE1NjA1MDgxMTF9.zPDgQn8VtzNkisn0E2p2cUCBAVMX0cvj9aKEkcu--KM");
byte[] responseBytes;
byte[] bytes = MergeContent();
try
{
responseBytes = webClient.UploadData(requestUrl, bytes);
String requestText = System.Text.Encoding.UTF8.GetString(bytes);
//打印字符串
Console.WriteLine(requestText);
//转换为字符串
responseText = System.Text.Encoding.UTF8.GetString(responseBytes);
//打印字符串
Console.WriteLine(responseText);
return true;
}
catch (WebException ex)
{
Stream responseStream = ex.Response.GetResponseStream();
responseBytes = new byte[ex.Response.ContentLength];
responseStream.Read(responseBytes, 0, responseBytes.Length);
}
responseText = System.Text.Encoding.UTF8.GetString(responseBytes);
return false;
}
/// <summary>
/// 设置表单数据字段
/// </summary>
/// <param name="fieldName">字段名</param>
/// <param name="fieldValue">字段值</param>
/// <returns></returns>
public void SetFieldValue(String fieldName, String fieldValue)
{
string httpRow = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n";
string httpRowData = String.Format(httpRow, fieldName, fieldValue);
bytesArray.Add(encoding.GetBytes(httpRowData));
}
/// <summary>
/// 设置表单文件数据
/// </summary>
/// <param name="fieldName">字段名</param>
/// <param name="filename">字段值</param>
/// <param name="contentType">内容内型</param>
/// <param name="fileBytes">文件字节流</param>
/// <returns></returns>
public void SetFieldValue(String fieldName, String filename, String contentType, Byte[] fileBytes)
{
string end = "\r\n";
string httpRow = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string httpRowData = String.Format(httpRow, fieldName, filename, contentType);
byte[] headerBytes = encoding.GetBytes(httpRowData);
byte[] endBytes = encoding.GetBytes(end);
byte[] fileDataBytes = new byte[headerBytes.Length + fileBytes.Length + endBytes.Length];
headerBytes.CopyTo(fileDataBytes, 0);
fileBytes.CopyTo(fileDataBytes, headerBytes.Length);
endBytes.CopyTo(fileDataBytes, headerBytes.Length + fileBytes.Length);
bytesArray.Add(fileDataBytes);
}
#endregion
}
参考:
https://www.cnblogs.com/haiyang21/p/9392399.html
https://blog.csdn.net/weixin_30750335/article/details/97895245