using HTEXScreen.Service; using Microsoft.AspNetCore.Mvc; using PuppeteerSharp; using System.Runtime.InteropServices; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using System.Web; namespace HTEXScreen.Controllers { [ApiController] [Route("screen")] public class ScreenController : ControllerBase { private readonly AzureStorageFactory _azureStorage; private readonly HttpClient _httpClient; public ScreenController(HttpClient httpClient, AzureStorageFactory azureStorage) { _httpClient = httpClient; _azureStorage = azureStorage; } [HttpPost("testbase64")] public async Task TestBase64(JsonElement json ) { JsonSerializerOptions option = new System.Text.Json.JsonSerializerOptions { Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; string name = "dataid"; var reg = $"(?<=\\b{name}=)[^&]*"; Regex regex = new Regex(reg); string decode= HttpUtility.UrlDecode("https://localhost:7298/swagger/index.html?dataid=%E5%BC%A0%E5%90%8C%E5%AD%A6&bs64=1234567&dataid=%E6%9D%8E%E5%90%8C%E5%AD%A6"); Match match= Regex.Match(decode, reg); string a = ""; while (match.Success) { a =a+$"{match.Value}"; match = match.NextMatch(); } string s = JsonSerializer.Serialize(json, option); string das= HttpUtility.UrlEncode(s,Encoding.UTF8); byte[] byts = Encoding.UTF8.GetBytes(s); var rdata = Convert.ToBase64String(byts); byte[] bs = Convert.FromBase64String(rdata); string data = Encoding.UTF8.GetString(bs); return Ok(new { a, rdata,das }); } [HttpGet("download")] public async Task Download([FromQuery] ScreenshotDto screenshot) { try { HttpResponseMessage response = await _httpClient.GetAsync(screenshot.url); if (!string.IsNullOrWhiteSpace(screenshot?.url)) { string? url = screenshot?.url; string[] path = url.Split("/"); string fileName = path[path.Length - 1]; fileName=HttpUtility.UrlDecode(fileName); Stream stream = response.Content.ReadAsStream(); if (!Directory.Exists("Download")){ Directory.CreateDirectory("Download"); } FileStream fs = new FileStream($"Download/{fileName}", FileMode.Create); byte[] bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); stream.Seek(0, SeekOrigin.Begin); BinaryWriter bw = new BinaryWriter(fs); bw.Write(bytes); bw.Close(); fs.Close(); return Ok(screenshot); } else { return Ok("链接为空"); } } catch (Exception ex) { return Ok($"{ex.Message}{ex.StackTrace}"); } } /// /// C#使用Puppeteer http://t.zoukankan.com/zhaotianff-p-13528507.html /// 文档https://learnku.com/docs/puppeteer/3.1.0/class-request/8559 /// https://www.w3cschool.cn/puppeteer/puppeteer-gp1737se.html /// /// /// [HttpGet("screenshot-png")] public async Task ScreenshotPng([FromQuery] ScreenshotDto screenshot) { // 进入容器的命令 docker exec -it f9e27d175498 /bin/bash //依赖包 https://blog.csdn.net/weixin_45447477/article/details/115188938 //sudo apt-get install libgdk-pixbuf2.0-0 libgdk-pixbuf-xlib-2.0-0 libdbusmenu-gtk3-4 libdbusmenu-glib4 libindicator3-7 ca-certificates fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils -y //解决ubuntu18上使用puppeteer https://blog.csdn.net/qq_42414062/article/details/114539378 //https://www.hardkoded.com/blog/running-puppeteer-sharp-azure-functions 使用。 //string url = "https://teammodelos.blob.core.chinacloudapi.cn/0-public/pie-borderRadius.html"; try { var bfOptions = new BrowserFetcherOptions(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { string dir = "/app"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } bfOptions.Path = dir; } var bf = new BrowserFetcher(bfOptions); var revisionInfo = bf.DownloadAsync(BrowserFetcher.DefaultChromiumRevision).Result; string BrowserExecutablePath = revisionInfo.ExecutablePath; var browser = await Puppeteer.LaunchAsync(new LaunchOptions { ExecutablePath = BrowserExecutablePath, Headless = true, Args = new string[] { "--no-sandbox", "--disable-setuid-sandbox" } }); var page = await browser.NewPageAsync(); bool fullPage = true; await page.SetViewportAsync(new ViewPortOptions { Width = screenshot.width, Height = screenshot.height });; fullPage = false; await page.GoToAsync(System.Web.HttpUtility.UrlDecode(screenshot.url)); Thread.Sleep(screenshot.delay); string base64 = await page.ScreenshotBase64Async(new ScreenshotOptions { FullPage = fullPage, BurstMode = true }); //关闭浏览器 await browser.CloseAsync(); await browser.DisposeAsync(); return Ok(new { url = base64 ,type= "data:image/png;base64," }); } catch (Exception ex) { return BadRequest($"{ex.Message}\n{ex.StackTrace}"); } } [HttpPost("screenshot-pdf")] public async Task ScreenshotPngs(ScreenshotDto screenshot) { //W3C School教程 https://www.w3cschool.cn/puppeteer/puppeteer-rip537tj.html // 进入容器的命令 docker exec -it f9e27d175498 /bin/bash //依赖包 https://blog.csdn.net/weixin_45447477/article/details/115188938 //sudo apt-get install libgdk-pixbuf2.0-0 libgdk-pixbuf-xlib-2.0-0 libdbusmenu-gtk3-4 libdbusmenu-glib4 libindicator3-7 ca-certificates fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils -y //解决ubuntu18上使用puppeteer https://blog.csdn.net/qq_42414062/article/details/114539378 //https://www.hardkoded.com/blog/running-puppeteer-sharp-azure-functions 使用。 //string url = "https://teammodelos.blob.core.chinacloudapi.cn/0-public/pie-borderRadius.html"; try { var bfOptions = new BrowserFetcherOptions(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { string dir = "/app"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } bfOptions.Path = dir; } var bf = new BrowserFetcher(bfOptions); var revisionInfo = bf.DownloadAsync(BrowserFetcher.DefaultChromiumRevision).Result; string BrowserExecutablePath = revisionInfo.ExecutablePath; var browser = await Puppeteer.LaunchAsync(new LaunchOptions { ExecutablePath = BrowserExecutablePath, Headless = true, Args = new string[] { "--no-sandbox", "--disable-setuid-sandbox" } }); ViewPortOptions viewPortOptions = new ViewPortOptions { Width = screenshot.width, Height = screenshot.height }; PdfOptions pdfOptions = new PdfOptions { DisplayHeaderFooter = true, PreferCSSPageSize =true}; //ScreenshotOptions screenshotOptions= new ScreenshotOptions { FullPage = fullPage, BurstMode = true }; int pagesize = 20; if (screenshot.urls.Count <= pagesize) { await PageToPdfStream(screenshot.urls,screenshot.fileNameKey,screenshot.cnt,browser,viewPortOptions,pdfOptions); } else { List tasks = new List(); int pages = (screenshot.urls.Count + pagesize) / pagesize; for (int i = 0; i < pages; i++) { var lists = screenshot.urls.Skip((i) * pagesize).Take(pagesize).ToList(); tasks.Add(PageToPdfStream(lists, screenshot.fileNameKey, screenshot.cnt, browser, viewPortOptions, pdfOptions)); } await Task.WhenAll(tasks); } //browser.NewPageAsync(); //foreach (var url in screenshot.urls) { // var page = await browser.NewPageAsync(); // await page.SetViewportAsync(viewPortOptions); // string file = $"E://pdfs//{Guid.NewGuid().ToString()}.pdf"; // var respons = await page.GoToAsync(System.Web.HttpUtility.UrlDecode(url), WaitUntilNavigation.Networkidle2); // if (respons.Ok) // { // await page.PdfAsync(file, pdfOptions); // // string base64 = await page.ScreenshotBase64Async(screenshotOptions); // } //} //关闭浏览器 await browser.CloseAsync(); await browser.DisposeAsync(); return Ok(); } catch (Exception ex) { return BadRequest($"{ex.Message}\n{ex.StackTrace}"); } } private async Task PageToPdfStream(List urls,string fileNameKey,string cnt , Browser browser, ViewPortOptions viewPortOptions, PdfOptions pdfOptions) { List> pages = new List>(); urls.ForEach(x => { pages.Add(browser.NewPageAsync()); }); var page_tasks = await Task.WhenAll(pages); List> responses = new List>(); page_tasks.ToList().ForEach(x => { x.SetViewportAsync(viewPortOptions); }); for (int i = 0; i < urls.Count; i++) { responses.Add(page_tasks[i].GoToAsync(System.Web.HttpUtility.UrlDecode(urls[i]), WaitUntilNavigation.Networkidle2)); } var responses_tasks = await Task.WhenAll(responses); //List> streams = new List>(); List tasks = new List(); List> uploads = new List>(); foreach (var page_task in page_tasks) { string url = page_task.Url; string[] paths= HttpUtility.UrlDecode(url).Split("/"); var reg = $"(?<=\\b{fileNameKey}=)[^&]*"; Regex regex = new Regex(reg); string decode = HttpUtility.UrlDecode(url); Match match = Regex.Match(decode, reg); string id = ""; while (match.Success) { id = id + $"{match.Value}"; match = match.NextMatch(); } //需要解析参数。paths[paths.Length-1] Stream stream = await page_task.PdfStreamAsync(pdfOptions); if (string.IsNullOrWhiteSpace(cnt)) { uploads.Add(_azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(stream, "artreport", $"{id}.pdf", true)); } else { uploads.Add(_azureStorage.GetBlobContainerClient(cnt).UploadFileByContainer(stream, "artreport", $"{id}.pdf", true)); } } string[] uploadUrls= await Task.WhenAll(uploads); page_tasks.ToList().ForEach(x => { tasks.Add(x.DisposeAsync().AsTask()); }); await Task.WhenAll(tasks); } private async Task PageToPdf(List urls, Browser browser, ViewPortOptions viewPortOptions, PdfOptions pdfOptions) { List> pages = new List>(); urls.ForEach(x => { pages.Add(browser.NewPageAsync()); }); var page_tasks = await Task.WhenAll(pages); List> responses = new List>(); page_tasks.ToList().ForEach(x => { x.SetViewportAsync(viewPortOptions); }); for (int i = 0; i < urls.Count; i++) { responses.Add(page_tasks[i].GoToAsync(System.Web.HttpUtility.UrlDecode(urls[i]), WaitUntilNavigation.Networkidle2)); } var responses_tasks = await Task.WhenAll(responses); List tasks = new List(); page_tasks.ToList().ForEach(x => { string file = $"{Guid.NewGuid()}.pdf"; tasks.Add(x.PdfAsync(file, pdfOptions)); }); await Task.WhenAll(tasks); tasks.Clear(); page_tasks.ToList().ForEach(x => { tasks.Add(x.DisposeAsync().AsTask()); }); await Task.WhenAll(tasks); } } } /// /// 网页截图参数 /// public class ScreenshotDto { public int width { get; set; } = 1920; public int height { get; set; } = 1080; public string? url { get; set; } /// /// 批量地址 /// public List urls { get; set; } = new List(); /// /// 提取参数的唯一id作为文件名 /// public string? fileNameKey { get; set; } /// /// 存在哪个容器里 /// public string? cnt { get; set; } public int delay { get; set; } }