1、前言
2024年末了一个月,家里多了个小公主,在家休息了一段时间。2025年,休完假上班第一天,领导就说:哎,我看总部那边做了个逐日产出的报表推送到钉钉群,来看筹划告竣率。我们基地这边能不能做啊。我内心默默一想,然后大声一喊能做(内心os:上家公司做过类似的功能,不外他们是自己的通讯工具,不是钉钉)。既然有了活,那就开干吧。终极忙活了几天,终于算是实现了这个功能吧,记载下整个过程,以及踩到的坑吧,终极实现效果如图。
2、下载帆软报表图片到本地<blockquote>6、总结
因为上家做过类似的功能,那就直接借鉴下之前的代码,先把帆软报表以图片格式下载到本地。大概过程如下
1、在帆软的报表访问页面的url后面添加&format=image&extype=PNG
2、使用http请求访问,下载到本地,添加动态反射以用来传帆软报表的查询条件参数
3、裁剪图片留白区域,添加水印等复制代码
- public async Task SendImageOutput()
- {
- try
- {
- //string fineReportUrl = "http://localhost:8075/webroot/decision/view/report?viewlet=tzreport/E04.cpt&format=image&extype=PNG";
- string image_Path = "D:\\1";
- string retMsg = string.Empty;
- DateTime dateTime = DateTime.Now;
- string time = dateTime.ToString("yyyyMMdd");//当前时间格式
- string downPath = Path.Combine(image_Path, time);//下载到当前的路径 //方便删除历史的记录文件
- if (!Directory.Exists(downPath))
- {
- Directory.CreateDirectory(downPath);
- }
- string startdate = dateTime.AddDays(-7).ToString("yyyy-MM-dd");
- string enddate = dateTime.ToString("yyyy-MM-dd");
- string cSharpScript = $"string startdate= "{startdate}";string enddate= "{enddate}"; var paramlist ="&startdate="+startdate+"&"+"enddate="+enddate; return paramlist;";
- string urlParam = FineReportUrlParam(cSharpScript);
- string url = fineReportUrl;
- if (!string.IsNullOrEmpty(urlParam))
- {
- url += urlParam;
- }
- //下载图片
- bool downResult = HttpDownloadImage(url, "C02产出", downPath, out string imageFullpath);
- if (downResult)
- {
- //发送数据到dingding
- .......
- }
- else
- {
- retMsg = "执行失败!";
- }
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
- /// <summary>
- /// http下载文件
- /// </summary>
- /// <param name="url">下载文件地址</param>
- /// <param name="path">文件存放地址</param>
- /// <param name="isAddSecurity">是否标密</param>
- /// <param name="imageNamePrefix">保存的文件的前缀</param>
- /// <param name="imageFullPath">图片保存到的本地路径</param>
- /// <returns></returns>
- public bool HttpDownloadImage(string url, string imageNamePrefix, string path, out string imageFullPath)
- {
- try
- {
- HttpWebRequest? request = WebRequest.Create(url) as HttpWebRequest;
- //发送请求并获取相应回应数据
- HttpWebResponse? response = request.GetResponse() as HttpWebResponse;
- string fileName = imageNamePrefix + "_" + DateTime.Now.ToString("yyyyMMddHHmmssFFF") + ".png";
- string fileFullPath = Path.Combine(path, fileName);
- Stream responseStream = response.GetResponseStream();
- ImageEditDomain imageEdit = new ImageEditDomain();
- Bitmap imageBitmap = imageEdit.CutImageWhitePart(responseStream, 80, fileFullPath);
- Bitmap imageBitmapSecret = imageBitmap;
- Bitmap imageBitmapWord = imageEdit.AddWatermarkWord(imageBitmapSecret);//加有“MES系统自动发送”的图片
- imageFullPath = string.Empty;
- if (imageBitmapWord == null)
- {
- return false;
- }
- else
- {
- imageBitmapWord.Save(fileFullPath, ImageFormat.Png);
- imageFullPath = fileFullPath;
- return true;
- }
- }
- catch (Exception ex)
- {
- imageFullPath = string.Empty;
- return false;
- }
- }
- /// <summary>
- /// 生成动态代码,方便调用
- /// </summary>
- /// <param name="argMethodCode"></param>
- /// <returns></returns>
- public string GenerateCode(string argMethodCode)
- {
- StringBuilder sb = new StringBuilder();
- sb.Append("using System;");
- sb.Append(Environment.NewLine);
- sb.Append("namespace FineReport");
- sb.Append(Environment.NewLine);
- sb.Append("{");
- sb.Append(Environment.NewLine);
- sb.Append(" public class UrlParam");
- sb.Append(Environment.NewLine);
- sb.Append(" {");
- sb.Append(Environment.NewLine);
- sb.Append(" public string GetParam()");
- sb.Append(Environment.NewLine);
- sb.Append(" {");
- sb.Append(Environment.NewLine);
- sb.Append(argMethodCode);
- sb.Append(Environment.NewLine);
- sb.Append(" }");
- sb.Append(Environment.NewLine);
- sb.Append(" }");
- sb.Append(Environment.NewLine);
- sb.Append("}");
- return sb.ToString();
- }
- /// <summary>
- /// 获取执行动态C#代码的值
- /// </summary>
- /// <param name="argCodeStr"></param>
- /// <returns></returns>
- public string FineReportUrlParam(string argCodeStr)
- {
- if (string.IsNullOrEmpty(argCodeStr))
- {
- return string.Empty;
- }
- string code = GenerateCode(argCodeStr);
- // CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
- //// CSharpCompilation objCSharpCodePrivoder = new CSharpCompilation();
- // CompilerParameters objCompilerParameters = new CompilerParameters();
- // objCompilerParameters.ReferencedAssemblies.Add("System.dll");
- // //objCompilerParameters.ReferencedAssemblies.Add("Newtonsoft.Json.dll");
- // objCompilerParameters.GenerateExecutable = false;
- // objCompilerParameters.GenerateInMemory = true;
- // CompilerResults cresult = objCSharpCodePrivoder.CompileAssemblyFromSource(objCompilerParameters, code);
- // // 通过反射,执行代码
- // Assembly objAssembly = cresult.CompiledAssembly;
- // object obj = objAssembly.CreateInstance("FineReport.UrlParam");
- // MethodInfo objMI = obj.GetType().GetMethod("GetParam");
- // return objMI.Invoke(obj, null)?.ToString();
- // Parse the source code into a syntax tree.
- var syntaxTree = CSharpSyntaxTree.ParseText(code);
- // Define the references that your compiled code will need.
- var references = new[]
- {
- MetadataReference.CreateFromFile(typeof(object).Assembly.Location), // mscorlib/System.Runtime.dll
- MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), // For example, if you use Console.WriteLine
- // Add other necessary references here, for example:
- // MetadataReference.CreateFromFile(typeof(Newtonsoft.Json.JsonConvert).Assembly.Location) // Newtonsoft.Json.dll
- };
- // Create a compilation object with the parsed code and references.
- var compilation = CSharpCompilation.Create(
- assemblyName: Path.GetRandomFileName(),
- syntaxTrees: new[] { syntaxTree },
- references: references,
- options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
- // Emit the compiled code into a memory stream.
- using (var ms = new MemoryStream())
- {
- var result = compilation.Emit(ms);
- if (!result.Success)
- {
- var failures = result.Diagnostics.Where(diagnostic =>
- diagnostic.IsWarningAsError ||
- diagnostic.Severity == DiagnosticSeverity.Error);
- throw new Exception("Compilation failed: " + string.Join(Environment.NewLine, failures.Select(d => d.ToString())));
- }
- else
- {
- ms.Seek(0, SeekOrigin.Begin);
- // Load the compiled assembly in a separate context to avoid locking issues.
- var loadContext = new AssemblyLoadContext(null, isCollectible: true);
- var assembly = loadContext.LoadFromStream(ms);
- // Use reflection to create an instance of the type and invoke its method.
- Type? type = assembly.GetType("FineReport.UrlParam");
- if (type == null)
- throw new InvalidOperationException("Type 'FineReport.UrlParam' not found.");
- object obj = Activator.CreateInstance(type)!;
- MethodInfo? methodInfo = type.GetMethod("GetParam");
- if (methodInfo == null)
- throw new InvalidOperationException("Method 'GetParam' not found.");
- return methodInfo.Invoke(obj, null)?.ToString();
- }
- }
- }
复制代码
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace DingDingTest
- {
- internal class ImageEditDomain
- {
- /// <summary>
- /// 剪去图片空余白边
- /// </summary>
- /// <param name="stream">源文件</param>
- /// <param name="WhiteBar">保留的白边,单位为像素</param>
- /// <param name="fullPath">保存到本地的地址</param>
- public Bitmap CutImageWhitePart(Stream stream, int WhiteBar, string fullPath)
- {
- Bitmap bmp = new Bitmap(stream);
- int top = 0, left = 0;
- int right = bmp.Width, bottom = bmp.Height;
- Color white = Color.White;
- //寻找最上面的标线,从左(0)到右,从上(0)到下
- for (int i = 0; i < bmp.Height; i++)//行
- {
- bool find = false;
- for (int j = 0; j < bmp.Width; j++)//列
- {
- Color c = bmp.GetPixel(j, i);
- if (IsWhite(c))
- {
- top = i;
- find = true;
- break;
- }
- }
- if (find) break;
- }
- //寻找最左边的标线,从上(top位)到下,从左到右
- for (int i = 0; i < bmp.Width; i++)//列
- {
- bool find = false;
- for (int j = top; j < bmp.Height; j++)//行
- {
- Color c = bmp.GetPixel(i, j);
- if (IsWhite(c))
- {
- left = i;
- find = true;
- break;
- }
- }
- if (find) break; ;
- }
- // 寻找最下边标线,从下到上,从左到右
- for (int i = bmp.Height - 1; i >= 0; i--)//行
- {
- bool find = false;
- for (int j = left; j < bmp.Width; j++)//列
- {
- Color c = bmp.GetPixel(j, i);
- if (IsWhite(c))
- {
- bottom = i;
- find = true;
- break;
- }
- }
- if (find) break;
- }
- //寻找最右边的标线,从上到下,从右往左
- for (int i = bmp.Width - 1; i >= 0; i--)//列
- {
- bool find = false;
- for (int j = 0; j <= bottom; j++)//行
- {
- Color c = bmp.GetPixel(i, j);
- if (IsWhite(c))
- {
- right = i;
- find = true;
- break;
- }
- }
- if (find) break;
- }
- int iWidth = right - left + 2;
- int iHeight = bottom - top + 2;
- bmp = Cut(bmp, left, top, iWidth, iHeight, WhiteBar);
- return bmp;
- }
- /// <summary>
- /// 添加文字:MES系统自动发送
- /// </summary>
- /// <param name="bitmap"></param>
- /// <returns></returns>
- public Bitmap AddWatermarkWord(Bitmap bitmap)
- {
- //添加MES系统标识
- string text = "MES系统自动发送";
- int fontSize = 10;
- Graphics g = Graphics.FromImage(bitmap);
- int rectWidth = text.Length * (fontSize + 10);
- int rectHeight = fontSize + 15;
- //声明矩形域
- Rectangle rectangle = new Rectangle(bitmap.Width - 200, bitmap.Height - 25, rectWidth, rectHeight);
- Font font = new Font("微软雅黑", fontSize, FontStyle.Bold); //定义字体
- SolidBrush backbrush = new SolidBrush(Color.Transparent);
- SolidBrush sbrushRed = new SolidBrush(Color.Red);
- var stringFormat = new StringFormat();
- stringFormat.Alignment = StringAlignment.Center;
- g.FillRectangle(backbrush, rectangle);
- g.DrawString(text, font, sbrushRed, rectangle, stringFormat);
- return bitmap;
- }
- /// <summary>
- /// 对图片进行裁剪
- /// </summary>
- /// <param name="b">要裁剪的图片</param>
- /// <param name="StartX">裁剪的X轴</param>
- /// <param name="StartY">裁剪的Y轴</param>
- /// <param name="iWidth">要裁剪的宽度</param>
- /// <param name="iHeight">要裁剪的高度</param>
- /// <param name="WhiteBar">保留的白边</param>
- /// <returns></returns>
- public Bitmap Cut(Bitmap b, int StartX, int StartY, int iWidth, int iHeight, int WhiteBar)
- {
- Bitmap bmpOut = new Bitmap(iWidth + 2 * WhiteBar, iHeight + 2 * WhiteBar, PixelFormat.Format24bppRgb);
- Graphics g = Graphics.FromImage(bmpOut);
- g.FillRectangle(Brushes.White, new Rectangle(0, 0, iWidth + 2 * WhiteBar, iHeight + 2 * WhiteBar));
- g.DrawImage(b, new Rectangle(WhiteBar, WhiteBar, iWidth, iHeight), new Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel);
- g.Dispose();
- return bmpOut;
- }
- /// <summary>
- /// 判断白色与否,非纯白色
- /// </summary>
- /// <param name="c"></param>
- /// <returns></returns>
- public bool IsWhite(Color c)
- {
- if (c.R < 245 || c.G < 245 || c.B < 245)
- return true;
- else return false;
- }
- }
- }
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) | Powered by Discuz! X3.4 |