需求场景:客户根据前台界面列表所选择的数据,根据需要的信息批量生成二维码并形成一张图片,并且每张图片显示的二维码数量是固定的,需要分页(即总共生成的二维码图片超出每页显示的需另起一页生成),并下载到客户端。

实现思路与技术:

主要用到技术: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程序-----批量生成二维码并形成一张图片的更多相关文章

  1. C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求

    C# 动态创建SQL数据库(二) 使用Entity Framework  创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...

  2. 微信小程序之生成二维码

    最近项目中涉及到小程序的生成二维码,很是头疼,经过多次摸索,整理出了自己的一些思想方法,如有不足,欢迎指正. 首先完全按照小程序的结构依次填坑. pages--index.wxml <view ...

  3. 小程序canvas生成二维码图片踩的坑

    1:生成临时图片,保证画布被加载以及渲染(即本身不可以 hidden 或是 上级元素不可以 hidden 或是 wx:if 隐藏等) == > 建议:因为 canvas 的组件层级(z-inde ...

  4. 在.net core web项目中生成二维码

    1.添加QRCoder包引用 2. public IActionResult MakeQrCode()        { string url="https://www.baidu.com& ...

  5. 小程序动态生成二维码,生成image图片

    前端: <image src="{{img_usrl}}" style="width:100%;height:104px;" bindlongtap=&q ...

  6. C# 利用QRCode生成二维码图片

    网上生成二维码的组件是真多,可是真正好用的,并且生成速度很快的没几个,QRCode就是我在众多中找到的,它的生成速度快.但是网上关于它的使用说明,真的太少了,大都是千篇一律的复制粘贴.这是本要用它做了 ...

  7. jquery.qrcode和jqprint的联合使用,实现html生成二维码并打印(中文也ok)

    在公司的生产现场中,常常会在一些部品或设备上贴上二维码,用于扫描录入数据,免去手动输入的麻烦. 以前曾经做过winform的程序,生成二维码,并打印出来,使用的是zxing的类库, 但是如果二维码是附 ...

  8. 在Excel中,不利用任何第三方工具,生成二维码

    有同事提需求,要批量生成二维码.谈了之后,我觉得可以做个excel文件,把要打印的内容放进去,然后给每行数据生成一个二维码.下一步就要在Excel里面生成二维码.问了一下度娘,貌似都得利用一些第三方工 ...

  9. 转【微信小程序 四】二维码生成/扫描二维码

    原文:https://blog.csdn.net/xbw12138/article/details/75213274 前端 二维码生成 二维码要求:每分钟刷新一次,模拟了个鸡肋,添加了个按分钟显示的时 ...

随机推荐

  1. winform项目导入数据

    一.点击导入按钮,弹出文件选择框 这个方法的使用要引用下面两个命名空间: using System.Windows.Forms;using DevExpress.XtraEditors; privat ...

  2. python+appium模拟手机物理按键操作

    一句代码:driver.keyevent()        括号里填入的是手机物理按键的数字代号 driver.press_keycode()        括号里填入的是键盘按键的数字代号 手机物理 ...

  3. Grains 与 Pillars

    Grains 与 Pillars Grains介绍 Grains接口是salt用来采集底层系统信息的,包含了操作系统信息.域名.IP地址.内核.内存等一些底层信息.就是因为grains采集了这些信息, ...

  4. 08--STL关联容器(set/multiset)

    一:set/multiset的简介 set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. set采用红黑树变体的数据结构实 ...

  5. 字符串join函数跟+号测试

    字符串join函数for循环+区别: 原因是这样的,字符串是不可变对象,当用操作符+连接字符串的时候,每执行一次+都会申请一块新的内存,然后复制上一个+操作的结果和本次操作的右操作符到这块内存空间,因 ...

  6. js 时间格式化 兼容safari 苹果手机

    export function formatTime (fmt, date) { date = new Date(date + '+08:00') // 兼容safari var o = { 'M+' ...

  7. unix域数据报回射程序(不完整)

    一.服务器程序 int main(int argc, char **argv) { int sockfd; struct sockaddr_un servaddr, cliaddr; sockfd = ...

  8. jmeter使用csv传参进行并发测试验证

    1.获取到注册接口,添加HTTP信息头管理器.HTTP请求,设置好入参,且检查使用csv文件传参的入参 2.创建csv文件,写入需要传的入参 3.添加CSV Data Set Config 设置配置 ...

  9. 找出链表中倒数第K个结点

    思路:两个指针,也是快指针和慢指针,先让快指针走k -1步,这时慢指针开始和快指针一起走到尾部.慢指针停止的点就是倒数第k个节点. public static ListNode findCountDo ...

  10. day 20 - 1 序列化模块,模块的导入

    序列化模块 首先我们来看一个序列:'sdfs45sfsgerg4454287789sfsf&*0' 序列 —— 就是字符串序列化 —— 从数据类型 --> 字符串的过程反序列化 —— 从 ...