Web程序-----批量生成二维码并形成一张图片
需求场景:客户根据前台界面列表所选择的数据,根据需要的信息批量生成二维码并形成一张图片,并且每张图片显示的二维码数量是固定的,需要分页(即总共生成的二维码图片超出每页显示的需另起一页生成),并下载到客户端。
实现思路与技术:
主要用到技术:Qrcode.net(生成二维码的库)
SharpZipLib(压缩库)
.NET GDI绘图
总体思路:根据相关的信息用Qrcode.net 与GDI绘图先绘制成单张二维码图片(如图1),然后再把多个单张生成的二维码按照每页需显示的个数再绘制到一张图上,可生成多张(如:图二),然后服务器再把类似多张(图二)的图片打包到一起,形成一个压缩文件(图三),下载到客户端。


(图1) (图二) (图三)
服务器端主要代码:
//生成二维码
public JsonResult MakeQrcodeImage([Json]List<EquipmentLedger_SheBei> list)
{
string virtual_Path="~/upload/EquipmentImage_Temp/"+Guid.NewGuid().ToString();
string folderName = Server.MapPath(virtual_Path);
Directory.CreateDirectory(folderName);
foreach (var li in list)
{
DrawQrCode(li, folderName);
}
int pageIndex = ;
int pageSize = ;
decimal totalCount =Convert.ToDecimal(list.Count);
decimal pages =Math.Ceiling(totalCount / pageSize);
List<string> fildes = new List<string>();
for (int i = ; i <= pages; i++)
{ var list_new = (from s in list
orderby s.Id descending
select s).Skip((pageIndex - ) * pageSize).Take(pageSize).ToList<EquipmentLedger_SheBei>(); CombineImage(list_new, pageIndex, folderName);
pageIndex++; } for (int j = ; j <= pages; j++){ fildes.Add(folderName + "/QrCodes-Page" + j + ".bmp"); }
string saveFile = folderName + "/QrCodesTest.zip";
Zip(fildes.ToArray(),saveFile);
return Json(new MyJsonResult() { success = true, data = virtual_Path + "/QrCodesTest" }, null, null); }
public FilePathResult DownLoadImage(string fieldName)
{ return File(Server.MapPath(fieldName) + ".zip", "application/octet-stream", "EquipmentLedgerQrCodes.zip"); }
//删除临时文件夹
public JsonResult DleteTempMakeQrcodeImage(string fieldName)
{ Directory.Delete(Server.MapPath(fieldName.Replace("/QrCodesTest","")),true);
return Json(new MyJsonResult() { success = true }, null, null); }
//绘制二维码
private void DrawQrCode(EquipmentLedger_SheBei eq,string folderName){
byte[] bytes = Encoding.Default.GetBytes(eq.Id.ToString());
string content = Convert.ToBase64String(bytes); ;
int moduleSize = ;
var encoder = new QrEncoder(ErrorCorrectionLevel.M);
QrCode qrCode = encoder.Encode(content);
GraphicsRenderer render = new GraphicsRenderer(new FixedModuleSize(moduleSize, QuietZoneModules.Four), Brushes.Black, Brushes.White);
DrawingSize dSize = render.SizeCalculator.GetSize(qrCode.Matrix.Width); RectangleF Rec_Top = new Rectangle(new Point(, ), new Size(dSize.CodeWidth, ));//顶部文字框
RectangleF Rec_botom_Num = new Rectangle(new Point(, dSize.CodeWidth - ), new Size(dSize.CodeWidth, ));//底部文字框
//创建画布
using (Bitmap map = new Bitmap(dSize.CodeWidth, dSize.CodeWidth))
{
Graphics g = Graphics.FromImage(map); g.Clear(Color.White);
Font drawFont = new Font("宋体", , FontStyle.Bold);
SolidBrush drawBrush = new SolidBrush(Color.Red);
render.Draw(g, qrCode.Matrix, new Point(, ));
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
g.DrawString(eq.Name, drawFont, drawBrush, Rec_Top, sf);
g.DrawString(eq.Number, drawFont, drawBrush, Rec_botom_Num, sf);
map.Save(folderName + "/" + eq.Id + ".bmp", ImageFormat.Bmp);//fileName为存放的图片路径
g.Dispose();
map.Dispose();//释放bmp文件资源 } }
private void Zip(string[] files, string ZipedFileName)
{
Zip(files, ZipedFileName, string.Empty);
}
private void Zip(string[] files, string ZipedFileName, string Password)
{
files = files.Where(f => System.IO.File.Exists(f)).ToArray();
if (files.Length != )
{
ZipOutputStream s = new ZipOutputStream(System.IO.File.Create(ZipedFileName));
s.SetLevel();
if (!string.IsNullOrEmpty(Password.Trim())) s.Password = Password.Trim();
ZipFileDictory(files, s);
s.Finish();
s.Close();
}
} /// <summary>
/// 压缩多个文件
/// </summary>
/// <param name="files">文件名</param>
/// <param name="ZipedFileName">压缩包文件名</param>
/// <returns></returns>
private void ZipFileDictory(string[] files, ZipOutputStream s)
{
ZipEntry entry = null;
FileStream fs = null;
Crc32 crc = new Crc32();
try
{
//创建当前文件夹
entry = new ZipEntry("/");
s.PutNextEntry(entry);
s.Flush();
foreach (string file in files)
{
//打开压缩文件
fs = System.IO.File.OpenRead(file); byte[] buffer = new byte[fs.Length];
fs.Read(buffer, , buffer.Length);
entry = new ZipEntry("/" + Path.GetFileName(file));
entry.DateTime = DateTime.Now;
entry.Size = fs.Length;
fs.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
s.PutNextEntry(entry);
s.Write(buffer, , buffer.Length);
}
}
finally
{
if (fs != null)
{
fs.Close();
fs = null;
}
if (entry != null)
entry = null;
GC.Collect();
}
}
//生成每页多张二维码的图片
private void CombineImage(List<EquipmentLedger_SheBei> list,int pageNum,string folderName)
{ int rows = ;
int cols = ;
int height = ;
int width = ;
int currentIndex = ; using (Bitmap bt1 = new Bitmap(, ))
{
List<Rectangle> recs = new List<Rectangle>();
Graphics g = Graphics.FromImage(bt1);
g.Clear(Color.White); for (int col = ; col < cols; col++)
{
for (int row = ; row < rows; row++)
{
if (list.Count >= currentIndex)
{ using (Bitmap bm = new Bitmap(folderName + "/" + list[currentIndex - ].Id + ".bmp"))
{
Rectangle rg = new Rectangle(col * height, row * width + row * +, width, height);
g.DrawImage(bm, rg);
currentIndex++;
}
}
}
}
//要绘制到的位图
bt1.Save(folderName + "/QrCodes-Page" + pageNum + ".bmp", ImageFormat.Bmp);//fileName为存放的图片路径
g.Dispose();
bt1.Dispose();//释放bmp文件资源
}
}
前端Extjs代码:
makeQrcodeImage: function () {
var me = this;
var record = me.getList().getSelectionModel().getSelection()[0];
if (record == null) {
Ext.Msg.alert("系统提示", "请选择要生成二维码图片的设备");
return;
} else {
var maiView = Ext.ComponentQuery.query('MainView')[0];
me.PicMask = new Ext.LoadMask(maiView, { msg: "图片生成中,请稍后..." });
me.PicMask.show();
var records = me.getList().getSelectionModel().getSelection();
var list = [];
for (var i = 0; i < records.length; i++) {
list.push(records[i].data);
}
Ext.Ajax.request({
url: "../../EquipmentLedgerSheBei/MakeQrcodeImage",
async: true,
scope: this,
params: {
list: Ext.util.base64.encode(Ext.JSON.encode(list)),
},
success: function (Response) {
var flag = Ext.JSON.decode(Response.responseText).success;
if (flag) {
//下载文件
window.open("../../EquipmentLedgerSheBei/DownLoadImage?fieldName=" + Ext.JSON.decode(Response.responseText).data, "_blank");
me.PicMask.hide();
Ext.Ajax.request({
url: "../../EquipmentLedgerSheBei/DleteTempMakeQrcodeImage",
async: true,
scope: this,
params: {
fieldName: Ext.JSON.decode(Response.responseText).data,
}
});
}
}
})
}
}
Web程序-----批量生成二维码并形成一张图片的更多相关文章
- C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求
C# 动态创建SQL数据库(二) 使用Entity Framework 创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...
- 微信小程序之生成二维码
最近项目中涉及到小程序的生成二维码,很是头疼,经过多次摸索,整理出了自己的一些思想方法,如有不足,欢迎指正. 首先完全按照小程序的结构依次填坑. pages--index.wxml <view ...
- 小程序canvas生成二维码图片踩的坑
1:生成临时图片,保证画布被加载以及渲染(即本身不可以 hidden 或是 上级元素不可以 hidden 或是 wx:if 隐藏等) == > 建议:因为 canvas 的组件层级(z-inde ...
- 在.net core web项目中生成二维码
1.添加QRCoder包引用 2. public IActionResult MakeQrCode() { string url="https://www.baidu.com& ...
- 小程序动态生成二维码,生成image图片
前端: <image src="{{img_usrl}}" style="width:100%;height:104px;" bindlongtap=&q ...
- C# 利用QRCode生成二维码图片
网上生成二维码的组件是真多,可是真正好用的,并且生成速度很快的没几个,QRCode就是我在众多中找到的,它的生成速度快.但是网上关于它的使用说明,真的太少了,大都是千篇一律的复制粘贴.这是本要用它做了 ...
- jquery.qrcode和jqprint的联合使用,实现html生成二维码并打印(中文也ok)
在公司的生产现场中,常常会在一些部品或设备上贴上二维码,用于扫描录入数据,免去手动输入的麻烦. 以前曾经做过winform的程序,生成二维码,并打印出来,使用的是zxing的类库, 但是如果二维码是附 ...
- 在Excel中,不利用任何第三方工具,生成二维码
有同事提需求,要批量生成二维码.谈了之后,我觉得可以做个excel文件,把要打印的内容放进去,然后给每行数据生成一个二维码.下一步就要在Excel里面生成二维码.问了一下度娘,貌似都得利用一些第三方工 ...
- 转【微信小程序 四】二维码生成/扫描二维码
原文:https://blog.csdn.net/xbw12138/article/details/75213274 前端 二维码生成 二维码要求:每分钟刷新一次,模拟了个鸡肋,添加了个按分钟显示的时 ...
随机推荐
- 【一本通1248:Dungeon Master&&洛谷UVA532 Dungeon Master】
若不会广搜转向[广搜] [题目描述] 这题是一个三维的迷宫题目,其中用‘.’表示空地,‘#’表示障碍物,‘S’表示起点,‘E’表示终点,求从起点到终点的最小移动次数,解法和二维的类似,只是在行动时除了 ...
- unittest 框架-待优化
模块1 :getdata.py 读取测试用例test_case.xlsx,返回测试用例结果 import json from openpyxl import load_workbook class D ...
- J.U.C-三剑客[semaphore\CyclicBarrier\CountDownLatch]
一.semaphore信号量,底层也是基于AQS 使用: /** * 可以理解为控制某个资源最多有多少个线程同时执行,(比如洗手间,并行与排队) * 如果满了只能等待直到其它资源释放(可以理解为并发量 ...
- 【Unity游戏开发】UGUI不规则区域点击的实现
一.简介 马三从上一家公司离职了,最近一直在出去面试,忙得很,所以这一篇博客拖到现在才写出来.马三在上家公司工作的时候,曾处理了一个UGUI不规则区域点击的问题,制作过程中也有一些收获和需要注意坑,因 ...
- MySql存储过程 CURSOR循环
游标 游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力. 使用步骤 声明一个游标: declare 游标名称 CU ...
- centos7安装与配置nginx1.11,开机启动
1.官网下载安装包 http://nginx.org/en/download.html,选择适合Linux的版本,这里选择最新的版本,下载到本地后上传到服务器或者centos下直接wget命令下载. ...
- 微信退款时候报”请求被中止: 未能创建 SSL/TLS 安全通道“或”The request was aborted: Could not create SSL/TLS secure channel“的错误
如题,英文中文表述的是一个意思 退款测试在我本机测试一切都是正常的,但是发布到了服务器就报这样的一个错啦 但是无论百度或者google或者bing,你能够搜索到的结果都很类似,综合起来就是加这样一些代 ...
- mesbox公告加更新控制
0为不显示,1为显示~~~~0|友情提示:任何时候,不要相信福利软件,福利网站,不乱接收别人发的的任何文件,如需使用军旗有关产品,请至官方群或官方网站下载!!|183|173~~~~162,1651, ...
- 【vue】函数式组件
在 2.5.0 及以上版本中,如果你使用了单文件组件,那么基于模板的函数式组件可以这样声明: <template functional> <div class="cell& ...
- 2018-2019 20165221 网络对抗 Exp5 MSF基础
2018-2019 20165221 网络对抗 Exp5 MSF基础 实践内容: 重点掌握metassploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 一个主动攻击实践,如ms0 ...