我具有条形码功能,该功能在本地环境下效果很好。但是,将条形码部署到天蓝色后,随机请求无法正常工作。
我已经下载了演示EAN13条码字体,并尝试使用以下代码来打印条码。
如果我在本地环境中请求多个请求,则它可以正常工作。部署到Azure之后,当我们一次请求多个请求时,它会随机返回错误的条形码。例如,失败案例10个请求中有3个。
c#条形码功能
public string GenerateBarCodeFont(string barCodeTextP, out bool isError, int widthP = 0, int heightP = 0, string fontNameP = "", int fontP = 0)
{
isError = false;
aa:
try
{
fontArray = new byte[0];
dataLength = 0;
if (widthP == 0)
widthP = 1;
if (heightP == 0)
heightP = 1;
if (fontP == 0)
fontP = 16;
fontArray = VLCEANThirtenBarCode.Properties.Resources.UPCEAN_0;
dataLength = VLCEANThirtenBarCode.Properties.Resources.UPCEAN_0.Length;
barCodeText = EAN13(barCodeTextP);
IntPtr destination = Marshal.AllocCoTaskMem(dataLength);
Marshal.Copy(fontArray, 0, destination, dataLength);
uint pcFonts = 0;
AddFontMemResourceEx(destination, (uint)fontArray.Length, IntPtr.Zero, ref pcFonts);
PrivateFontCollection fonts = new PrivateFontCollection();
fonts.AddMemoryFont(destination, dataLength);
Marshal.FreeCoTaskMem(destination);
this.ff = fonts.Families[0];
int num3 = heightP * 2;
int num5 = Convert.ToInt32((double)(Convert.ToDouble(widthP) * 1.5));
int num6 = (heightP * 100) / 90;
Font font = new Font(this.ff, (float)fontP);
PointF point = new PointF(2f, 2f);
Bitmap bitmap = new Bitmap(widthP, heightP, PixelFormat.Format24bppRgb);
bitmap.SetResolution((float)num6, (float)num6);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.FillRectangle(new SolidBrush(Color.White), 0, 0, widthP, heightP);
graphics.DrawString(barCodeText, font, new SolidBrush(Color.Black), point);
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
byte[] inArray = stream.ToArray();
Convert.ToBase64String(inArray);
barCodeText = Convert.ToBase64String(inArray, 0, inArray.Length);
}
bitmap.Dispose();
}
catch (Exception ex)
{
if (ex.Message == "A generic error occurred in GDI+.")
goto aa;
isError = true;
return ex.Message;
}
return barCodeText;
}
EAN13 BarCodefont逻辑
public string EAN13(string bcP)
{
string s = "", suppl = "", TempStrL = "";
int CountryFlagL = 0;
switch (bcP.Length)
{
case 12:
case 13:
s = bcP.Substring(0, 12) + CheckDigit(SYMB_EAN13, bcP.Substring(0, 12));
break;
case 14:
case 15:
s = bcP.Substring(0, 12) + CheckDigit(SYMB_EAN13, bcP.Substring(0, 12));
suppl = AddOn(bcP.Substring(bcP.Length - 2));
break;
case 17:
case 18:
s = bcP.Substring(0, 12) + CheckDigit(SYMB_EAN13, bcP.Substring(0, 12));
suppl = AddOn(bcP.Substring(bcP.Length - 5));
break;
}
TempStrL = GetChar(digitsOnly, s.Substring(0, 1));//
TempStrL = TempStrL + "{{{{{";
TempStrL = TempStrL + "|";
CountryFlagL = Convert.ToInt32(s.Substring(0, 1));//
for (int i = 1; i <= 6; i++)
{
if (GetParity(SYMB_EAN13, i - 1, CountryFlagL) == "A")//
TempStrL = TempStrL + GetChar(charsetA, s.Substring(i, 1));//
else
TempStrL = TempStrL + GetChar(charsetB, s.Substring(i, 1));//
}
TempStrL = TempStrL + "{" + "|" + "{";
for (int i = 8; i <= 13; i++)
{
TempStrL = TempStrL + GetChar(charsetC, s.Substring(i - 1, 1));
}
TempStrL = TempStrL + "|";
if (suppl.Length > 0)
TempStrL = TempStrL + "}" + suppl;
return TempStrL;
}
protected string AddOn(string bcP)
{
string parL, ParSectionL = "", TempstrL;
int TotalL = 0, intbcL, MultiplierL, PositionL, CounterL = 0, SectLengthL;
switch (bcP.Length)
{
case 2:
parL = "AA" + "AB" + "BA" + "BB";
intbcL = Convert.ToInt32(bcP);
TotalL = intbcL % 4;
ParSectionL = parL.Substring(TotalL * 2, 2);
break;
case 5:
parL = "BBAAA" + "BABAA" + "BAABA" + "BAAAB" + "ABBAA" + "AABBA" + "AAABB" + "ABABA" + "ABAAB" + "AABAB";
for (int i = 1; i <= 5; i++)
{
MultiplierL = 3;
if (i % 2 == 0)
MultiplierL = 9;
intbcL = Convert.ToInt32(bcP.Substring(i - 1, 1));
TotalL = TotalL + MultiplierL * intbcL;
}
PositionL = (TotalL % 10) * 5;
ParSectionL = parL.Substring(PositionL, 5);
break;
}
TempstrL = "m";
SectLengthL = ParSectionL.Length;
for (int i = 1; i <= SectLengthL; i++)
{
if (ParSectionL.Substring(i - 1, 1) == "A")
TempstrL = TempstrL + GetChar(CharsetASupp, bcP.Substring(i - 1, 1));
else
TempstrL = TempstrL + GetChar(CharsetBSupp, bcP.Substring(i - 1, 1));
if (i < SectLengthL)
TempstrL = TempstrL + "n";
}
return TempstrL;
}
protected string CheckDigit(int SymbologyL, string c)
{
string s = "";
int NumDigitsL = 0, intc = 0, cd;
decimal TotalL = 0;
switch (SymbologyL)
{
case SYMB_UPCA:
NumDigitsL = 11;
break;
case SYMB_EAN13:
NumDigitsL = 12;
break;
case SYMB_EAN8:
NumDigitsL = 7;
break;
}
for (int i = 1; i <= NumDigitsL; i++)
{
if (((NumDigitsL + 1 - i) % 2) == 0)
{
string str = c.Substring(i - 1, 1);
intc = Convert.ToInt32(str);
TotalL = TotalL + 1 * intc;
}
else
{
string str = c.Substring(i - 1, 1);
intc = Convert.ToInt32(str);
TotalL = TotalL + 3 * intc;
}
}
cd = 10 - Convert.ToInt32(TotalL % 10);
if (cd == 10)
cd = 0;
return cd.ToString();
}
protected string GetChar(string c, string DigitP)
{
int intDigitL = Convert.ToInt32(DigitP);
return c.Substring(intDigitL, 1);
}
protected string GetParity(int SymbologyP, int PositionP, int CodeValP)
{
string parL = "", ParityL = "";
switch (SymbologyP)
{
case SYMB_EAN13:
parL = "AAAAAA" + "AABABB" + "AABBAB" + "AABBBA" + "ABAABB" + "ABBAAB" + "ABBBAA" + "ABABAB" + "ABABBA" + "ABBABA";
break;
case SYMB_UPCE:
parL = "BBBAAA" + "BBABAA" + "BBAABA" + "BBAAAB" + "BABBAA" + "BAABBA" + "BAAABB" + "BABABA" + "BABAAB" + "BAABAB";
break;
}
ParityL = parL.Substring(CodeValP * 6, 6);
return ParityL.Substring(PositionP, 1);
}
**全局变量低于**
[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbfont, uint cbfont, IntPtr pdv, [In] ref uint pcFonts);
FontFamily ff;
private string barCodeText = string.Empty;
byte[] fontArray;
int dataLength;
const int SYMB_UPCA = 1, SYMB_EAN13 = 3, SYMB_EAN8 = 4, SYMB_UPCE = 2;
string CharsetASupp = "+,./:;=?@K", CharsetBSupp = @"LMNOP[\]^_";
string charsetA = "ABCDEFGHIJ", charsetB = "QRSTUVWXYZ", charsetC = "0123456789", digitsOnly = "qrstuvwxyz";
正确的如下所示
下面显示的是错误的
我已经创建了上述函数的vlcbarcode.dll文件引用,并添加了与refered url相同的azure项目,并写入了下面的函数。
下面是天蓝色函数
[FunctionName("GetBarCodes")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "GetBarCodes/")]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// Get request body
VLCBarCodes[] barCodeList = await req.Content.ReadAsAsync<VLCBarCodes[]>();
List<QueryStringClass> resultList = new List<QueryStringClass>();
string errorText = "";
string result = "";
bool isError = false;
foreach (var list in barCodeList)
{
errorText = "";
result = "";
if (string.IsNullOrWhiteSpace(list.BarCodeFontType))
errorText = " Bar code Type can not be empty or null";
if (string.IsNullOrWhiteSpace(list.BarCodeValue))
errorText += " Bar code text can not be empty or null";
if (string.IsNullOrWhiteSpace(list.BarCodeFontHeight))
errorText += " Bar code height can not be empty or null";
if (string.IsNullOrWhiteSpace(list.BarCodeFontWidth))
errorText += " Bar code width can not be empty or null";
if (string.IsNullOrWhiteSpace(list.BarCodeFontSize))
errorText += " Bar code font can not be empty or null";
if (list.BarCodeImageUID == 0)
errorText += " Bar Code Image Id can not be empty or null";
if (string.IsNullOrWhiteSpace(list.BarCodeEntryNo))
errorText += " Bar Code entry no can not be empty or null";
if (!string.IsNullOrWhiteSpace(list.BarCodeFontType) && !string.IsNullOrWhiteSpace(list.BarCodeValue) && !string.IsNullOrWhiteSpace(list.BarCodeFontHeight)
&& !string.IsNullOrWhiteSpace(list.BarCodeFontWidth) && list.BarCodeImageUID != 0 && string.IsNullOrWhiteSpace(errorText))
{
switch (list.BarCodeFontType)
{
case "EAN-13":
GenerateEANTBarCode generateEANTBarCode = new GenerateEANTBarCode();
result = generateEANTBarCode.GenerateBarCodeFont(list.BarCodeValue, out isError, Convert.ToInt32(list.BarCodeFontWidth), Convert.ToInt32(list.BarCodeFontHeight), "EAN-13", Convert.ToInt32(list.BarCodeFontSize));
break;
default:
isError = true;
result = "Please specify the bar code font type";
break;
}
if (isError)
resultList.Add(new QueryStringClass { BarCodeEntryNo = list.BarCodeEntryNo, BarCodeImageUID = list.BarCodeImageUID, Type = list.BarCodeFontType, Value = "", ErrorText = result });
else
resultList.Add(new QueryStringClass { BarCodeEntryNo = list.BarCodeEntryNo, BarCodeImageUID = list.BarCodeImageUID, Type = list.BarCodeFontType, Value = result, ErrorText = "" });
}
else
resultList.Add(new QueryStringClass { BarCodeEntryNo = list.BarCodeEntryNo, BarCodeImageUID = list.BarCodeImageUID, Type = list.BarCodeFontType, Value = result, ErrorText = errorText });
}
return req.CreateResponse(HttpStatusCode.OK, resultList);
}
QueryStringClass可以从vlcbarcode.dll函数获取结果并返回给最终用户。
public class QueryStringClass
{
public int BarCodeImageUID { get; set; }
//public Guid Guid { get; set; }
public string BarCodeEntryNo { get; set; }
public string Type { get; set; }
public string Value { get; set; }
public string ErrorText { get; set; }
}
VLCBarCodes类是指原始calss字段,用于验证请求并将值发送到.dll文件功能。
public class VLCBarCodes
{
public int BarCodeImageUID { get; set; }
public string BarCodeValue { get; set; }
public string BarCodeFontWidth { get; set; }
public string BarCodeFontHeight { get; set; }
public string BarCodeFontType { get; set; }
public string BarCodeFontSize { get; set; }
public string BarCodeEntryNo { get; set; }
}
请建议我是否做错了事。
答案 0 :(得分:2)
在Azure App服务中,大多数GDI32系统调用均被阻止。
所有Azure Web应用程序(以及移动应用程序/服务,WebJob和功能)都在称为沙箱的安全环境中运行。
沙箱通常旨在限制对Windows共享组件的访问。不幸的是,Windows的许多核心组件已被设计为共享组件:注册表,加密和图形子系统,等等。本节概述了在使用这些经常必不可少但共享的组件时所受到的限制。
为了大大减少攻击表面积,沙盒阻止了几乎所有Win32k.sys API的调用,这实际上意味着大多数User32 / GDI32系统调用均被阻止。对于大多数应用程序来说,这不是问题,因为大多数Azure Web Apps不需要访问Windows UI功能(毕竟它们是Web应用程序)。
参考文档:https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox
如果愿意使用相同的代码,则可以将此Azure函数托管在Azure虚拟机中,否则,您可以尝试一些替代方法来生成BAR代码,如this blog.
中所述