(C#)根据文字信息,生成电子凭证(图片)

实现目的:

        财务中有收保证金与加盟费的操作,纸质的发票保存起来容易丢失,并且不容易查找,于是要改用电子收据的方式来实现:电子收据的样式,是根据实际的纸质收据截图进来的,如下图。我们要实现的是,一旦收据数据从前台传入到后台,后台就根据数据合成一张收据图片并上传服务器:

   

实现代码:

A.电子收据中实体定义:

public class ElectronicReceipt : IDbTracking

{

[Key]

/// <summary>
///
/// </summary>
public int PKID { get; set; }

/// <summary>
/// 账单ID
/// </summary>
public int StateId { get; set; }
public int ShopId { get; set; }

private string shopName = string.Empty;
/// <summary>
/// 收据编号
/// </summary>
public string ShopName
{
get { return this.shopName ?? string.Empty; }
set { this.shopName = value; }
}

private string receiptNo = string.Empty;
/// <summary>
/// 收据编号
/// </summary>
public string ReceiptNo
{
get { return this.receiptNo ?? string.Empty; }
set { this.receiptNo = value; }
}

private string bizType = string.Empty;
/// <summary>
/// 业务单据类型
/// </summary>
public string BizType
{
get { return this.bizType ?? string.Empty; }
set { this.bizType = value; }
}

/// <summary>
/// 入账日期
/// </summary>
public System.DateTime ReceivedDate { get; set; }

private string paidBusiness = string.Empty;
/// <summary>
/// 交款单位
/// </summary>
public string PaidBusiness
{
get { return this.paidBusiness ?? string.Empty; }
set { this.paidBusiness = value; }
}

private string receiveMethod = string.Empty;
/// <summary>
/// 收款方式
/// </summary>
public string ReceiveMethod
{
get { return this.receiveMethod ?? string.Empty; }
set { this.receiveMethod = value; }
}

/// <summary>
/// 人民币
/// </summary>
public decimal ReceiveAmount { get; set; }

private string receiveRemark = string.Empty;
/// <summary>
/// 收款事由
/// </summary>
public string ReceiveRemark
{
get { return this.receiveRemark ?? string.Empty; }
set { this.receiveRemark = value; }
}

private string createdBy = string.Empty;
/// <summary>
/// 创建人
/// </summary>
public string CreatedBy
{
get { return this.createdBy ?? string.Empty; }
set { this.createdBy = value; }
}

private string urlImg = string.Empty;
/// <summary>
/// 创建人
/// </summary>
public string UrlImg
{
get { return this.urlImg ?? string.Empty; }
set { this.urlImg = value; }
}

/// <summary>
/// 创建人
/// </summary>
public System.DateTime CreateTime { get; set; }

/// <summary>
/// 最后更新时间
/// </summary>
public System.DateTime LastUpdateTime { get; set; }

private string receiveAmountChinese = string.Empty;
/// <summary>
///
/// </summary>
public string ReceiveAmountChinese
{
get { return this.receiveAmountChinese ?? string.Empty; }
set { this.receiveAmountChinese = value; }
}

private string optionStatus = string.Empty;
/// <summary>
///
/// </summary>
public string OptionStatus
{
get { return this.optionStatus ?? string.Empty; }
set { this.optionStatus = value; }
}
/// <summary>
/// 是否删除
/// </summary>
public bool IsDeleted { get; set;}

/// <summary>
///费用属性(Normal:基础,Upgrade:升级)
/// </summary>
public string CostAttribute { get; set; }


public override string ToString()
{
return new StringBuilder()
.AppendLine($"账单ID:{this.StateId}")
.AppendLine($"收据编号:{this.ReceiptNo}")
.AppendLine($"业务单据类型:{this.BizType}")
.AppendLine($"入账日期:{this.ReceivedDate}")
.AppendLine($"交款单位:{this.PaidBusiness}")
.AppendLine($"收款方式:{this.ReceiveMethod}")
.AppendLine($"人民币:{this.ReceiveAmount}")
.AppendLine($"收款事由:{this.ReceiveRemark}")
.AppendLine($"创建人:{this.CreatedBy}")
.AppendLine($"费用属性:{this.CostAttribute}")
.AppendLine($"创建时间:{this.CreateTime}")
.AppendLine($"最后更新时间:{this.LastUpdateTime}")
.ToString();
}
}

B.定义封装绘制图片的类 

//把文字合成到切图中去,相当于是加水印的方式

public class DrawImg
{
public static byte[] DrawWords(WaterImage image)
{
// 源图片全路径
string sourcePictureName = image.PicturePath + image.SourcePicture;
string fileExtension = System.IO.Path.GetExtension(sourcePictureName).ToLower();
// 判断文件是否存在,以及文件名是否正确
if (System.IO.File.Exists(sourcePictureName) == false || (
fileExtension != ".gif" &&
fileExtension != ".jpg" &&
fileExtension != ".png"))
{
return null;
}

// 目标图片名称及全路径
string targetImage = sourcePictureName.Replace(System.IO.Path.GetExtension(sourcePictureName), "") + "_" + DateTime.Now.ToString("yyyyMMddhhmmssfff") + ".jpg";
//创建一个图片对象用来装载要被添加水印的图片
Image imgPhoto = Image.FromFile(sourcePictureName);
//获取图片的宽和高
int phWidth = imgPhoto.Width;
int phHeight = imgPhoto.Height;

//建立一个bitmap,和我们需要加水印的图片一样大小
Bitmap bmPhoto = new Bitmap(phWidth, phHeight, PixelFormat.Format24bppRgb);
//SetResolution:设置此 Bitmap 的分辨率
//这里直接将我们需要添加水印的图片的分辨率赋给了bitmap
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
//Graphics:封装一个 GDI+ 绘图图面。
Graphics grPhoto = Graphics.FromImage(bmPhoto);

//设置图形的品质
grPhoto.SmoothingMode = SmoothingMode.AntiAlias;

//将我们要添加水印的图片按照原始大小描绘(复制)到图形中
grPhoto.DrawImage(
imgPhoto, // 要添加水印的图片
new Rectangle(0, 0, phWidth, phHeight), // 根据要添加的水印图片的宽和高
0, // X方向从0点开始描绘
0, // Y方向
phWidth, // X方向描绘长度
phHeight, // Y方向描绘长度
GraphicsUnit.Pixel); // 描绘的单位,这里用的是像素


//根据图片的大小我们来确定添加上去的文字的大小
//在这里我们定义一个数组来确定
int[] sizes = new int[] { 16, 14, 12, 10, 8, 6, 4 };

//字体
Font crFont = null;
//矩形的宽度和高度,SizeF有三个属性,分别为Height高,width宽,IsEmpty是否为空
SizeF crSize = new SizeF();
int yPixlesFromBottom = (int)(phHeight * .05);


foreach (var wordInfo in image.words)
{
//利用一个循环语句来选择我们要添加文字的型号
//直到它的长度比图片的宽度小
for (int i = 0; i < 7; i++)
{
crFont = new Font("arial", sizes[i], FontStyle.Bold);

//测量用指定的 Font 对象绘制并用指定的 StringFormat 对象格式化的指定字符串。
crSize = grPhoto.MeasureString(wordInfo.Words, crFont);

// ushort 关键字表示一种整数数据类型
if ((ushort)crSize.Width < (ushort)phWidth)
break;
}

//封装文本布局信息(如对齐、文字方向和 Tab 停靠位),显示操作(如省略号插入和国家标准 (National) 数字替换)和 OpenType 功能。
StringFormat StrFormat = new StringFormat();

//定义需要印的文字居中对齐
StrFormat.Alignment = StringAlignment.Near;
SolidBrush semiTransBrush = new SolidBrush(wordInfo.color);
//绘制图形
grPhoto.DrawString(wordInfo.Words, //string of text
crFont, //font
semiTransBrush, //Brush
new PointF(wordInfo.Position.xPosOfPic, wordInfo.Position.yPosOfPic), //Position
StrFormat);
}
//imgPhoto是我们建立的用来装载最终图形的Image对象
//bmPhoto是我们用来制作图形的容器,为Bitmap对象
imgPhoto = bmPhoto;
//释放资源,将定义的Graphics实例grPhoto释放,grPhoto功德圆满
grPhoto.Dispose();

//将grPhoto保存
//将图片上传服务器,并保存
//将图片保存在文件服务器上

var imgPhotoByte = ConvertImage(imgPhoto);
imgPhoto.Dispose();
return imgPhotoByte;
//保存文件
//imgPhoto.Save(targetImage, ImageFormat.Jpeg);
}


/// <summary>
/// 将Image转换为byte[] 用来存放是数据库中
/// </summary>
/// <param name="image">Image</param>
/// <returns>byte[]</returns>
public static byte[] ConvertImage(Image image)
{
using (var bitMag = new Bitmap(image))
{
using (var stream = new MemoryStream())
{
bitMag.Save(stream, ImageFormat.Jpeg);
var bateArr = stream.ToArray();
return bateArr;
}
}
}
}

//准备要合成的图片的原材料信息(图片与要合成的字)

public class WaterImage
{
public WaterImage()
{
words = new List<WaterWord>();
}

/// <summary>
/// 文件名称
/// </summary>
public string SourcePicture;
/// <summary>
/// 文件地址
/// </summary>
public string PicturePath;
/// <summary>
/// 要打水印的文字
/// </summary>
public List<WaterWord> words { get; set; }
}

///要合成的字的样式,位置,大小的配置类

public class WaterWord
{
public WaterWord()
{
Alpha = (float)0.9;
//字体颜色
color = Color.FromArgb(255, 0, 0, 0);
}

/// <summary>
/// 透明度 0-1
/// </summary>
public float Alpha;
public ImagePosition Position;
public string Words;
/// <summary>
/// 文字的颜色
/// </summary>
public Color color { get; set; }
}

///要加入图片的位置信息

public class ImagePosition
{
public ImagePosition()
{
xPosOfPic = 0;
yPosOfPic = 0;
}

public float xPosOfPic { get; set; }
public float yPosOfPic { get; set; }
}

//组装操作  绘制图片并上传文件

public string UploadReceiveVoucherDoc(ElectronicReceipt er)
{
if (er == null)
{
return string.Empty;
}

var waterImag = new WaterImage()
{
PicturePath = AppDomain.CurrentDomain.BaseDirectory,
SourcePicture = @"ReceiveVoucher.jpg",
};

EnvironmentHandler.Instance.Logger.Log(Level.Info, waterImag.PicturePath + waterImag.SourcePicture, "图片的模板地址");

//收据号码
waterImag.words.Add(new WaterWord()
{
Words = er.ReceiptNo,
Position = new ImagePosition() { xPosOfPic = 1000, yPosOfPic = 70 }
});
//入账日期
waterImag.words.Add(new WaterWord()
{
Words = er.ReceivedDate.ToString("yyyy MM dd"),
Position = new ImagePosition() { xPosOfPic = 660, yPosOfPic = 148 }
});
//交款单位
waterImag.words.Add(new WaterWord()
{
Words = er.CreatedBy,
Position = new ImagePosition() { xPosOfPic = 311, yPosOfPic = 245 }
});
//收款方式
waterImag.words.Add(new WaterWord()
{
Words = er.PaidBusiness,
Position = new ImagePosition() { xPosOfPic = 970, yPosOfPic = 245 }
});
//人民币(大写)
var words = er.ReceiveAmountChinese;
if (er.ReceiveAmount - (int)er.ReceiveAmount == 0 && !words.EndsWith("整"))
{
words += "整";
}
waterImag.words.Add(new WaterWord()
{
Words = words,
Position = new ImagePosition() { xPosOfPic = 329, yPosOfPic = 322 }
});
//人民币(小写)
waterImag.words.Add(new WaterWord()
{
Words = er.ReceiveAmount.ToString("0.00"),
Position = new ImagePosition() { xPosOfPic = 928, yPosOfPic = 315 }
});
//收款事由
waterImag.words.Add(new WaterWord()
{
Words = "【" + er.ShopId + "】-" + er.ReceiveRemark,
Position = new ImagePosition() { xPosOfPic = 294, yPosOfPic = 404 }
});
//落款年月
waterImag.words.Add(new WaterWord()
{
Words = DateTime.Now.ToString("yyyy MM dd"),
Position = new ImagePosition() { xPosOfPic = 928, yPosOfPic = 462 }
});
var bitys = DrawImg.DrawWords(waterImag);
EnvironmentHandler.Instance.Logger.Log(Level.Info, bitys.ToString(), "图片二进制");
if (bitys != null)
{
var fileDirectory = @"/finance/ShopBillReceiptVoucher/" + DateTime.Now.ToString("yyyyMMdd");
var uploadRequest = new ImageUploadRequest(fileDirectory, bitys);

//上传文件到服务器上,封装的上传方法,根据各自的情况而定
var filePath = UploadImageAsync(uploadRequest).Result;
EnvironmentHandler.Instance.Logger.Log(Level.Info, filePath, "UploadReceiveVoucherDoc 图片的地址");
return filePath;
}
return "";
}

原文地址:https://www.cnblogs.com/q994321263/p/10973603.html