C# RSClientPrint 非常大的线轴

发布于 2024-10-31 21:14:53 字数 5220 浏览 2 评论 0原文

我正在使用带有 DB2 后端的 ASP .Net 3.5 MVC1。我的公司正在尝试从 Microsoft SQL Server 2008 RSCLient 打印 GDI+ 对话框打印条形码。我们无法将文件保存为 PDF 并在本地打印,因为这是用于我们的实物库存应用程序,并且员工可能会使用本地条形码做坏事(它们是良好的检查),因此我们被迫通过 HTTP 进行打印并控制其打印。每个商店都有一个本地打印服务器,但 Web 服务器位于公司 IT 办公室。我相信我必须使用 .jpeg,因为 .gif 会导致条形码中的线条模糊并且无法被扫描枪读取。

该应用程序在处理数百个标签时工作正常(大约 5 页,大约需要 5 分钟才能完成打印后台处理),但打印 2000 个标签需要 2 小时(接近 300 页,大约 +150 MB)。我在应用程序上运行 Wireshark 来尝试捕获来回的数据包,并将信息传递到网络,这就是他们的响应。

不。时间源 目的地 协议信息 36628 653.373235 HTTP [TCP 窗口已满] 连续或非 HTTP 流量 36630 654.245430 TCP [TCP ZeroWindowProbe] http> 35503 [ACK] Seq=26291213 Ack=3730 Win=63137 Len=1

我离题了。我的问题是我可以使用什么类型的策略来帮助加快 HTTP 上的后台打印速度。我应该在 X 页上“砍掉”打印线轴并重新打印其余部分吗?我应该改变我的打印算法吗?有什么方法可以缩小打印线轴的大小而不损失 .jpeg 质量?是否有 RSClientPrint 的开源或商业替代方案可以处理我需要的业务逻辑?

现在开始编码吧!如果您还需要任何其他信息,请告诉我!

        [AcceptVerbs(HttpVerbs.Post)]
    [Authorization(Roles = Roles.NonInquiry)]
    public ActionResult ReprintLabels(int eventId, int areaCode, int lowerLabelNumber, int upperLabelNumber)
    {
        if (!_eventAreaService.IsAreaEditable(eventId, areaCode))
            return RedirectToAction("Index", new { eventId = eventId });

        var printContext = _eventAreaService.ReprintLabels(eventId, areaCode, lowerLabelNumber, upperLabelNumber);

        ActionResult result = RedirectToAction("Index", new { eventId = eventId });
        if (printContext != null)
        {
            var redirectUrl = Url.RouteUrl(new { controller = "EventArea", action = "Index", eventId = eventId });
            Session[PrintContextViewModel.SessionKey] = new PrintContextViewModel(printContext, redirectUrl);

            result = RedirectToAction("PrintLabels", "LabelPrint");
        }

        return result;
    }

public InventoryAreaPrintContext ReprintLabels(int eventId, int areaCode, int lowerLabelBound, int upperLabelBound)
    {
        var user = _authentication.CurrentUser;

        if (user.IsInRole(Roles.CorporateInquiry) || user.IsInRole(Roles.StoreInquiry))
            throw new InvalidOperationException("User must be a non-inquiry role.");

        List<Fixture> fixturesToVoid = GetLabelsInRange(eventId, areaCode, lowerLabelBound, upperLabelBound).Where(f => f.StatusCode == FixtureStatus.Ready).ToList();

        if (fixturesToVoid.Count < 1) return null;

        // Void all old labels and tally the labels that to be recreated
        //      for each area involved.
        var voidFixturesByArea = new Dictionary<int, int>();
        foreach (var f in fixturesToVoid)
        {
            if (!voidFixturesByArea.ContainsKey(f.AreaCode))
                voidFixturesByArea[f.AreaCode] = 1;
            else
                voidFixturesByArea[f.AreaCode]++;

            f.StatusCode = FixtureStatus.VoidReplace;
            _fixtureRepo.Update(f);
        }

        var storeEvent = _storeEventRepository.FindEvent(user.DefaultStore, eventId);
        var lastUsedLabel = storeEvent.LastUsedLabelNumber;
        var affectedAreas = new List<InventoryArea>();

        // Create new labels for the affected areas.
        foreach (var pair in voidFixturesByArea)
        {
            var area = _areaRepo.FindByKey(user.DefaultStore.GroupCode, user.DefaultStore.ID, eventId, pair.Key);
            var fixtures = _fixtureBuilder.AddFixtures(lastUsedLabel.Value, area, pair.Value);
            fixtures.ForEach(f => _fixtureRepo.Insert(f));

            area.Fixtures = fixtures;
            affectedAreas.Add(area);
        }

        // Update the store event counts.
        var numberOfLabels = fixturesToVoid.Count();

        storeEvent.LastUsedLabelNumber += numberOfLabels;

        _storeEventRepository.Update(storeEvent);

        return new InventoryAreaPrintContext(_barcodeGenerator) { InventoryAreas = affectedAreas, StoreEvent = storeEvent, Store = user.DefaultStore };
    }

public class BarcodeGenerator : IBarcodeGenerator
{
    private readonly BarCodeImage.CodeSetEncoder _codeSetEncoder;

    public BarcodeGenerator(BarCodeImage.CodeSetEncoder codeSetEncoder)
    {
        _codeSetEncoder = codeSetEncoder;
    }

    public byte[] CreateBarcode(string barcodeText)
    {
        byte[] data;
        var generator = new BarCodeImage(barcodeText, _codeSetEncoder, true)
                            {
                                InsetText = false,
                                Font = new Font(
                                    FontFamily.GenericSansSerif,
                                    10,
                                    FontStyle.Regular,
                                    GraphicsUnit.Pixel)
                            };

        /** 
         * Keep the image dimensions at the same ratio as they will be displayed in the report.
         * Currently the report is set to a height to width ratio of 1/5 so we set the image
         * height to width at 1/5 as well. Otherwise the barcode will not scan properly.
         **/
        using (var image = generator.Render(50, 250))
        using (var ms = new MemoryStream())
        {
            image.Save(ms, ImageFormat.Jpeg);
            data = ms.GetBuffer();
        }

        return data;
    }
}

I am using ASP .Net 3.5 MVC1 with a DB2 backend. My company is trying to print Barcodes from the Microsoft SQL Server 2008 RSCLient Print GDI+ dialog box. We can't save files to a PDF and print local because this is for our Physical Inventory Application, and associates might could do bad stuff with local Barcodes (they are as good checks) so we are forced to print over HTTP and control their printing. Each store has a print server on location, but the web server is located in the corporate IT office. I believe i have to use a .jpeg because a .gif will cause the lines in the barcode to blur and not be readable by a scanning gun.

The application works fine with a few hundred tags (about 5 pages and about 5 min to finish the print spool), but it takes 2 hours to print 2000 tags (close to 300 pages about +150 MB). I ran Wireshark on the application to try and catch the packets coming back and forth, and passed the information on to networking and this was their response.

NO. Time Source Destination Protocol Info
36628 653.373235 HTTP [TCP Window Full] Continuation or non-HTTP traffic
36630 654.245430 TCP [TCP ZeroWindowProbe] http > 35503 [ACK] Seq=26291213 Ack=3730 Win=63137 Len=1

I digress on the back story. My question is what type of strategy can i use to help speed up the print spool over HTTP. Should i "chop" the print spool off at X pages and re spool the rest? Should i change my printing algorithm? What would be a way to shrink my size of my print spool without losing the .jpeg quality? Is there and opensource or commercial alternative to RSClientPrint that will handle the business logic i need?

Now for coding goodness! If you need anything else please let me know!

        [AcceptVerbs(HttpVerbs.Post)]
    [Authorization(Roles = Roles.NonInquiry)]
    public ActionResult ReprintLabels(int eventId, int areaCode, int lowerLabelNumber, int upperLabelNumber)
    {
        if (!_eventAreaService.IsAreaEditable(eventId, areaCode))
            return RedirectToAction("Index", new { eventId = eventId });

        var printContext = _eventAreaService.ReprintLabels(eventId, areaCode, lowerLabelNumber, upperLabelNumber);

        ActionResult result = RedirectToAction("Index", new { eventId = eventId });
        if (printContext != null)
        {
            var redirectUrl = Url.RouteUrl(new { controller = "EventArea", action = "Index", eventId = eventId });
            Session[PrintContextViewModel.SessionKey] = new PrintContextViewModel(printContext, redirectUrl);

            result = RedirectToAction("PrintLabels", "LabelPrint");
        }

        return result;
    }

public InventoryAreaPrintContext ReprintLabels(int eventId, int areaCode, int lowerLabelBound, int upperLabelBound)
    {
        var user = _authentication.CurrentUser;

        if (user.IsInRole(Roles.CorporateInquiry) || user.IsInRole(Roles.StoreInquiry))
            throw new InvalidOperationException("User must be a non-inquiry role.");

        List<Fixture> fixturesToVoid = GetLabelsInRange(eventId, areaCode, lowerLabelBound, upperLabelBound).Where(f => f.StatusCode == FixtureStatus.Ready).ToList();

        if (fixturesToVoid.Count < 1) return null;

        // Void all old labels and tally the labels that to be recreated
        //      for each area involved.
        var voidFixturesByArea = new Dictionary<int, int>();
        foreach (var f in fixturesToVoid)
        {
            if (!voidFixturesByArea.ContainsKey(f.AreaCode))
                voidFixturesByArea[f.AreaCode] = 1;
            else
                voidFixturesByArea[f.AreaCode]++;

            f.StatusCode = FixtureStatus.VoidReplace;
            _fixtureRepo.Update(f);
        }

        var storeEvent = _storeEventRepository.FindEvent(user.DefaultStore, eventId);
        var lastUsedLabel = storeEvent.LastUsedLabelNumber;
        var affectedAreas = new List<InventoryArea>();

        // Create new labels for the affected areas.
        foreach (var pair in voidFixturesByArea)
        {
            var area = _areaRepo.FindByKey(user.DefaultStore.GroupCode, user.DefaultStore.ID, eventId, pair.Key);
            var fixtures = _fixtureBuilder.AddFixtures(lastUsedLabel.Value, area, pair.Value);
            fixtures.ForEach(f => _fixtureRepo.Insert(f));

            area.Fixtures = fixtures;
            affectedAreas.Add(area);
        }

        // Update the store event counts.
        var numberOfLabels = fixturesToVoid.Count();

        storeEvent.LastUsedLabelNumber += numberOfLabels;

        _storeEventRepository.Update(storeEvent);

        return new InventoryAreaPrintContext(_barcodeGenerator) { InventoryAreas = affectedAreas, StoreEvent = storeEvent, Store = user.DefaultStore };
    }

public class BarcodeGenerator : IBarcodeGenerator
{
    private readonly BarCodeImage.CodeSetEncoder _codeSetEncoder;

    public BarcodeGenerator(BarCodeImage.CodeSetEncoder codeSetEncoder)
    {
        _codeSetEncoder = codeSetEncoder;
    }

    public byte[] CreateBarcode(string barcodeText)
    {
        byte[] data;
        var generator = new BarCodeImage(barcodeText, _codeSetEncoder, true)
                            {
                                InsetText = false,
                                Font = new Font(
                                    FontFamily.GenericSansSerif,
                                    10,
                                    FontStyle.Regular,
                                    GraphicsUnit.Pixel)
                            };

        /** 
         * Keep the image dimensions at the same ratio as they will be displayed in the report.
         * Currently the report is set to a height to width ratio of 1/5 so we set the image
         * height to width at 1/5 as well. Otherwise the barcode will not scan properly.
         **/
        using (var image = generator.Render(50, 250))
        using (var ms = new MemoryStream())
        {
            image.Save(ms, ImageFormat.Jpeg);
            data = ms.GetBuffer();
        }

        return data;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

九公里浅绿 2024-11-07 21:14:53

将图像包装发送到后台打印程序时出现了一些问题。我最后做的是使用 iTextSharp 的条形码 128 类,基本上用字体而不是图像构建条形码,然后对于人类可读的文本,我只是传入条形码对象的固定标签字符串并将该值设置为我的值.RDLC 报告。如果有人想要任何代码,请随时PM我。

Something was fishy in sending the image wrapper to the print spooler. What i wound up doing was to use iTextSharp's barcode 128 class and basically build the barcode out of a font instead of an image, then for human readable text i just passed in my barcode object's fixture tag string and set that value to a value on my .RDLC report. If anyone wants any code please feel free to PM me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文