From 3dd406260fe28518499ccc2423d5f56e98902e89 Mon Sep 17 00:00:00 2001 From: SHM Date: Wed, 14 May 2025 09:17:06 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=84=B1=ED=98=84=EB=AA=A8]=20VPKI=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=95,=20csv=20=EB=8B=A4=EC=9A=B4?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Projects/DLL/SystemX.Core.dll | Bin 41472 -> 43008 bytes .../SystemX.Core/Communication/Http.cs | 34 ++++ .../Model/CertificateHistoryModel.cs | 2 + .../Services/CertificateService.cs | 13 +- .../Controllers/CommonController.cs | 2 +- .../Controllers/VPKIBaseController.cs | 46 ++++- .../Services/ISO15118_02Service.cs | 6 +- .../Services/ISO15118_20Service.cs | 14 +- .../VPKI.Web.Api/Services/VpkiBaseService.cs | 30 +++- .../Components/Pages/VPKIManager.razor | 160 ++++++++++-------- .../VPKI.Web.Client/wwwroot/js/scripts.js | 27 ++- 11 files changed, 213 insertions(+), 121 deletions(-) diff --git a/Projects/DLL/SystemX.Core.dll b/Projects/DLL/SystemX.Core.dll index 637fb5e0fdf565ce68a5553d4a01eee86e62d287..b057bf57dd216b0918574fc5b8625db2d4826d90 100644 GIT binary patch delta 16913 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 diff --git a/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs b/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs index 4bd12ad..9c92073 100644 --- a/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs +++ b/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs @@ -95,6 +95,40 @@ namespace SystemX.Core.Communication return response; } + public virtual async Task GetStreamAsync(string url, string bearerToken = "", short timeOutSeconds = 10) + { + Guid guid = Guid.NewGuid(); + + Stream stream = null; + + using (HttpClient httpClient = new HttpClient(GetClientHandler())) + { + try + { + var timeOutSec = SetTimeout(timeOutSeconds); + httpClient.Timeout = new TimeSpan(0, 0, timeOutSec); + httpClient.BaseAddress = new Uri($"{url}"); + + if (string.IsNullOrEmpty(bearerToken) == false) + httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $"{bearerToken}"); + + Log4net.WriteLine($"[GET] Request({guid})::{url}", LogType.HTTP); + + DateTime requestTime = DateTime.Now; + var response = await httpClient.GetAsync(url); + stream = await response.Content.ReadAsStreamAsync(); + + Log4net.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogType.HTTP); + } + catch (Exception e) + { + Log4net.WriteLine(e); + } + } + + return stream; + } + protected HttpClientHandler GetClientHandler() { diff --git a/Projects/VPKI/VPKI/VPKI.Library/Model/CertificateHistoryModel.cs b/Projects/VPKI/VPKI/VPKI.Library/Model/CertificateHistoryModel.cs index 133e478..fdced43 100644 --- a/Projects/VPKI/VPKI/VPKI.Library/Model/CertificateHistoryModel.cs +++ b/Projects/VPKI/VPKI/VPKI.Library/Model/CertificateHistoryModel.cs @@ -14,5 +14,7 @@ namespace VPKI.Library.Model public TCertificate? TCertificate { get; set; } public TVerifyResult? TVerifyResult { get; set; } public TOcsp? TOcsp { get; set; } + + public int TotalCount { get; set; } } } diff --git a/Projects/VPKI/VPKI/VPKI.Library/Services/CertificateService.cs b/Projects/VPKI/VPKI/VPKI.Library/Services/CertificateService.cs index dfc7e3b..fc3931a 100644 --- a/Projects/VPKI/VPKI/VPKI.Library/Services/CertificateService.cs +++ b/Projects/VPKI/VPKI/VPKI.Library/Services/CertificateService.cs @@ -573,12 +573,7 @@ namespace VPKI.Library.Services hashedCsr.SignedCsr = GetKeyBase64Encrypted(vnSignedHash); hashedCsr.EncodedSignedCsr = GetKeyBase64Encrypted(vnDEREncVal); - hashedCsr.Verify = bVerfRst; - - Log4net.WriteLine($"SignHashed02 csr::{csr}", LogType.Fatal); - Log4net.WriteLine($"SignHashed02 Public Key::{GetKeyBase64Encrypted(GetPublicKeyBC(keyPair)!.Q.GetEncoded()!.ToList())}", LogType.Fatal); - Log4net.WriteLine($"SignHashed02 SignedCsr::{hashedCsr.SignedCsr}", LogType.Fatal); - Log4net.WriteLine($"SignHashed02 EncodedSignedCsr::{hashedCsr.EncodedSignedCsr}", LogType.Fatal); + hashedCsr.Verify = bVerfRst; var decoded = DecodeDERSignature_02(vnDEREncVal); @@ -601,11 +596,7 @@ namespace VPKI.Library.Services List vnSignedHash = GetBouncyCastleECDSASignedHashKey(vnRHashVal, GetPrivateKeyBC(keyPair), ECDSAType.NONEWITHECDSA); List vnDEREncVal = EncodeDERSignature_20(vnSignedHash); bool bVerfRst = VerifyHashBC(vnSignedHash, vnRHashVal, GetPublicKeyBC(keyPair), ECDSAType.NONEWITHECDSA); - - Log4net.WriteLine($"SignHashed20 csr::{csr}", LogType.Fatal); - Log4net.WriteLine($"SignHashed20 Public Key::{GetKeyBase64Encrypted(GetPublicKeyBC(keyPair)!.Q.GetEncoded()!.ToList())}", LogType.Fatal); - Log4net.WriteLine($"SignHashed20 bVerfRst::{bVerfRst}", LogType.Fatal); - + hashedCsr.SignedCsr = GetKeyBase64Encrypted(vnSignedHash); hashedCsr.EncodedSignedCsr = GetKeyBase64Encrypted(vnDEREncVal); hashedCsr.Verify = bVerfRst; diff --git a/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/CommonController.cs b/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/CommonController.cs index 9cbca4c..ded161d 100644 --- a/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/CommonController.cs +++ b/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/CommonController.cs @@ -8,7 +8,7 @@ using VPKI.Library.Services; namespace VPKI.Web.Api.Controllers { - public class CommonController + public class CommonController : ControllerBase { public readonly IServiceProvider _serviceProvider; public readonly IHttpContextAccessor _httpContextAccessor; diff --git a/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIBaseController.cs b/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIBaseController.cs index 28c3638..4b36407 100644 --- a/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIBaseController.cs +++ b/Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIBaseController.cs @@ -1,7 +1,12 @@ -using Microsoft.AspNetCore.Http; +using DB.VPKI_DataDB; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; +using System.IO; +using System.Text; using VPKI.Library.Enums; using VPKI.Library.Model; +using VPKI.Library.Static; using VPKI.Web.Api.Services; namespace VPKI.Web.Api.Controllers @@ -19,7 +24,7 @@ namespace VPKI.Web.Api.Controllers [Tags("VPKI API Base")] [HttpGet] [Route("history")] - public async Task TbscsrHistory(DateTime startDate, DateTime endDate) + public async Task TbscsrHistory(DateTime startDate, DateTime endDate, [FromQuery] TTbscsr filter, int page = 1) { List response = new List(); @@ -27,7 +32,7 @@ namespace VPKI.Web.Api.Controllers var service = _serviceProvider.GetService(); if (service != null) { - response = await service.History(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate)); + response = await service.History(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate), filter, page); } long min = 0; @@ -129,5 +134,40 @@ namespace VPKI.Web.Api.Controllers return Results.Ok(response); } + + /// + /// csv + /// + [Tags("VPKI API Base")] + [HttpGet] + [Route("exportCsv")] + [ApiExplorerSettings(IgnoreApi = false)] + public async Task ExportCsv(DateTime startDate, DateTime endDate, [FromQuery] TTbscsr filter) + { + Log4net.WriteLine(GetRequestLog().LogModelToString("Request"), LogType.CONTROLLER); + + var sb = new StringBuilder(); + int row = 0; + + var service = _serviceProvider.GetService(); + if (service != null) + { + var csvData = await service.History(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate), filter, -1); + row = csvData.Count; + + foreach (var line in csvData.ConvertToCsvFile()) + { + sb.AppendLine(line); + } + } + Log4net.WriteLine($"Response::Export CSV, {row} Rows", LogType.CONTROLLER); + + // UTF-8 BOM 포함 (Excel에서 깨지지 않도록 하기 위해) + var bom = Encoding.UTF8.GetPreamble(); + var csvBytes = Encoding.UTF8.GetBytes(sb.ToString()); + var resultBytes = bom.Concat(csvBytes).ToArray(); + + return File(resultBytes, "text/csv", $"VPKI_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.csv"); + } } } diff --git a/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_02Service.cs b/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_02Service.cs index f7b0d5a..548e0f2 100644 --- a/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_02Service.cs +++ b/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_02Service.cs @@ -180,11 +180,7 @@ namespace VPKI.Web.Api.Services } else { - var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}"; - Log4net.WriteLine($"Failed HashedTbscsr::{csr.CHashedTbscsr}", LogType.Fatal); - Log4net.WriteLine($"Failed Signature::{request.csrsignature}", LogType.Fatal); - Log4net.WriteLine($"Failed PublicKey::{csr.CPublickey}", LogType.Fatal); - Log4net.WriteLine($"Failed PublicKey::{publicKeyPem}", LogType.Fatal); + var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}"; } } catch (Exception e) diff --git a/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_20Service.cs b/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_20Service.cs index 7167197..109300d 100644 --- a/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_20Service.cs +++ b/Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_20Service.cs @@ -42,10 +42,10 @@ namespace VPKI.Web.Api.Services request.certType = VpkiType.vehicle_cert.ToString(); } - string pcid = _certificateService.CreatePCID(request, VpkiType.prov_v1); - string dn = $"cn={_certificateService.CreatePCID(request, VpkiType.prov_cert)},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}"; - if (request.certType == VpkiType.vehicle_cert.ToString() || request.certType == VpkiType.evcc_cert.ToString()) - dn = $"cn={_certificateService.CreatePCID(request, VpkiType.vehicle_cert)},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}"; + string pcid = _certificateService.CreatePCID(request, VpkiType.vehicle_cert); + if (request.certType == VpkiType.evcc_cert.ToString()) + pcid = _certificateService.CreatePCID(request, VpkiType.evcc_cert); + string dn = $"cn={pcid},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}"; string csrOrigin = _certificateService.CreateCsr512(dn, request.publickey); string tbaCsrHashed = string.Empty; @@ -191,11 +191,7 @@ namespace VPKI.Web.Api.Services } else { - var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}"; - Log4net.WriteLine($"Failed HashedTbscsr::{csr.CHashedTbscsr}", LogType.Fatal); - Log4net.WriteLine($"Failed Signature::{request.csrsignature}", LogType.Fatal); - Log4net.WriteLine($"Failed PublicKey::{csr.CPublickey}", LogType.Fatal); - Log4net.WriteLine($"Failed PublicKey::{publicKeyPem}", LogType.Fatal); + var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}"; } } catch (Exception e) diff --git a/Projects/VPKI/VPKI/VPKI.Web.Api/Services/VpkiBaseService.cs b/Projects/VPKI/VPKI/VPKI.Web.Api/Services/VpkiBaseService.cs index 2bcc700..8b697ac 100644 --- a/Projects/VPKI/VPKI/VPKI.Web.Api/Services/VpkiBaseService.cs +++ b/Projects/VPKI/VPKI/VPKI.Web.Api/Services/VpkiBaseService.cs @@ -1,10 +1,12 @@ using Azure; using DB.VPKI_DataDB; using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage; +using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; using Microsoft.Extensions.FileSystemGlobbing.Internal; using Microsoft.Identity.Client; +using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Utilities.Collections; using System.Collections.Generic; @@ -44,10 +46,13 @@ namespace VPKI.Web.Api.Services } #region 공통 사용 함수 - public async Task> History(DateOnly startDate, DateOnly endDate) + public async Task> History(DateOnly startDate, DateOnly endDate, TTbscsr filter, int page = 1) { List response = new List(); - + + int rowCount = 20; + int totalCount = 0; + using (var scope = _scopeFactory.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); @@ -56,7 +61,22 @@ namespace VPKI.Web.Api.Services using (var transaction = await context.CreateTransactionAsync(System.Data.IsolationLevel.ReadUncommitted)) { var getList = await context.TTbscsrs.AsNoTracking().Where(x => startDate <= DateOnly.FromDateTime(x.CDateTime.Date) - && DateOnly.FromDateTime(x.CDateTime.Date) <= endDate).ToListAsync(); + && DateOnly.FromDateTime(x.CDateTime.Date) <= endDate + && EF.Functions.Like(x.CIftid, $"%{filter.CIftid}%") + && EF.Functions.Like(x.CMacaddr, $"%{filter.CMacaddr}%") + && EF.Functions.Like(x.CWmi, $"%{filter.CWmi}%") + && EF.Functions.Like(x.CIdType, $"%{filter.CIdType}%") + && EF.Functions.Like(x.CSupplierId, $"%{filter.CSupplierId}%") + && EF.Functions.Like(x.CDc, $"%{filter.CDc}%") + && EF.Functions.Like(x.CTierCode, $"%{filter.CTierCode}%") + && EF.Functions.Like(x.CUnitCode, $"%{filter.CUnitCode}%") + && EF.Functions.Like(x.CCertType, $"%{filter.CCertType}%") + && EF.Functions.Like(x.CPcid, $"%{filter.CPcid}%")).OrderByDescending(x=>x.CCuid).ToListAsync(); + + totalCount = getList.Count; + if(page >= 0) + getList = getList.Skip((page - 1) * rowCount).Take(rowCount).ToList(); + response.AddRange(getList.Select(x => new CertificateHistoryModel { TTbscsr = x, TCertificate = null })); foreach (var r in response) @@ -72,6 +92,8 @@ namespace VPKI.Web.Api.Services var ocspResult = await context.TOcsps.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == r!.TTbscsr!.CCuid); if (ocspResult != null) r.TOcsp = ocspResult; + + r.TotalCount = totalCount; } await context.CloseTransactionAsync(transaction); @@ -292,7 +314,7 @@ namespace VPKI.Web.Api.Services return subCaFile; } - + #endregion } } diff --git a/Projects/VPKI/VPKI/VPKI.Web.Client/Components/Pages/VPKIManager.razor b/Projects/VPKI/VPKI/VPKI.Web.Client/Components/Pages/VPKIManager.razor index bbc595d..bfff43b 100644 --- a/Projects/VPKI/VPKI/VPKI.Web.Client/Components/Pages/VPKIManager.razor +++ b/Projects/VPKI/VPKI/VPKI.Web.Client/Components/Pages/VPKIManager.razor @@ -31,38 +31,29 @@ - Search + Search - - + @* + *@
-
+ @*
-
+
*@
- - + + @* *@
- + - - - @* - - *@ - @foreach (var prop in typeof(TTbscsr).GetProperties()) { @@ -71,7 +62,29 @@ continue; string propName = $"{prop.Name}"; - + //filter 없음 + if (propName.ToLower().Contains("ccuid")) + { + + + + } + else if (propName.ToLower().Contains("chascertificate")) + { + + + + } + //filter 있음 + else + { + + + } } @@ -160,6 +173,8 @@ } + + @@ -172,16 +187,17 @@ private DateOnly SearchStartDate = DateOnly.FromDateTime(DateTime.Now.AddDays(-7)); private DateOnly SearchEndDate = DateOnly.FromDateTime(DateTime.Now); - private string FilterIft = string.Empty; - private string FilterWMI = string.Empty; - private string FilterDC = string.Empty; - private string FilterCertType = string.Empty; + string pagingSummaryFormat = "Page{0}/{1} (Total:{2} Rows)"; - private int ViewCount = 20; + private int PageTotalRowCount = 0; + private int PageViewCount = 10; + private int PageSizeCount = 20; List history = new List(); RadzenDataGrid grid = new(); + Dictionary DicFilter = new Dictionary(); + protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) @@ -191,7 +207,7 @@ await Task.CompletedTask; } - private async Task Search(int startCcuid) + private async Task Search(int page = 1) { DialogService.OpenIndicator("Search History"); @@ -200,33 +216,23 @@ //Default filter requestUrl += $"startDate={SearchStartDate}&"; requestUrl += $"endDate={SearchEndDate}&"; + // requestUrl += $"startCcuid={startCcuid}&"; //optional filter - // if (string.IsNullOrEmpty(FilterIft) == false) - // { - // requestUrl += $"ift={FilterIft}&"; - // } - // if (string.IsNullOrEmpty(FilterWMI) == false) - // { - // requestUrl += $"wmi={FilterWMI}&"; - // } - // if (string.IsNullOrEmpty(FilterDC) == false) - // { - // requestUrl += $"dc={FilterDC}&"; - // } - // if (string.IsNullOrEmpty(FilterCertType) == false) - // { - // requestUrl += $"certType={FilterCertType}&"; - // } + foreach (var filter in grid.Query.Filters) + { + requestUrl += $"{filter.Property.Split('.').Last()}={filter.FilterValue}&"; + } + requestUrl += $"page={page}"; history?.Clear(); var http = new Http(); var result = await http.GetJsonAsync>(requestUrl); - if (result != null) - { + if (result?.Count > 0) + { + PageTotalRowCount = result.First().TotalCount; history.AddRange(result); - history.Reverse(); } grid?.Reload(); @@ -345,51 +351,58 @@ DialogService.CloseIndicator(); } - async Task OnClickExportCSV(bool isFilter = false) + async Task OnClickExportCSV() { DialogService.OpenIndicator("Export to CSV"); - List exportData = new List(); + var http = new Http(); + string requestUrl = $"https://{ServerAddress}/exportCsv?"; - if (isFilter == true) - { - //필터링된 데이터만 - exportData.AddRange(grid.View.ToList().ConvertToCsvFile()); - } - else - { - //전체 데이터 - exportData.AddRange(history.ConvertToCsvFile()); - } + //Default filter + requestUrl += $"startDate={SearchStartDate}&"; + requestUrl += $"endDate={SearchEndDate}&"; - if (exportData?.Count > 0) + // requestUrl += $"startCcuid={startCcuid}&"; + + //optional filter + foreach (var filter in grid.Query.Filters) { - string fileName = $"VPKI_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.csv"; - bool exportResult = await JS.InvokeAsync("openSaveFileCSV", fileName, exportData.ToJson()); + requestUrl += $"{filter.Property.Split('.').Last()}={filter.FilterValue}&"; + } + var csv = await http.GetStreamAsync(requestUrl, timeOutSeconds: 30); + + string fileName = $"VPKI_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.csv"; + if(csv != null) + { + using var streamRef = new DotNetStreamReference(stream: csv); + + bool exportResult = await JS.InvokeAsync("openSaveFileCSV", fileName, streamRef); if (exportResult == true) { - NotiService.Notify(new NotificationMessage - { - Severity = NotificationSeverity.Success, - Summary = "Success", - Detail = "CSV Export Success" - }); + NotiService.Notify(new NotificationMessage + { + Severity = NotificationSeverity.Success, + Summary = "Success", + Detail = "CSV Export Success" + }); } else { NotiService.Notify(new NotificationMessage - { - Severity = NotificationSeverity.Error, - Summary = "Failed", - Detail = "CSV Export Failed", - }); + { + Severity = NotificationSeverity.Error, + Summary = "Failed", + Detail = "CSV Export Failed", + }); } } DialogService.CloseIndicator(); } - void OnChangeFilter() + void OnChangeFilter(DataGridColumnFilterEventArgs args) { + PageTotalRowCount = 0; + history?.Clear(); StateHasChanged(); } @@ -522,5 +535,10 @@ Detail = "Copy To Clipboard Failed.", }); } + } + + private async Task PageChanged(PagerEventArgs args) + { + await Search(args.PageIndex + 1); } } diff --git a/Projects/VPKI/VPKI/VPKI.Web.Client/wwwroot/js/scripts.js b/Projects/VPKI/VPKI/VPKI.Web.Client/wwwroot/js/scripts.js index 255f26f..7bd4467 100644 --- a/Projects/VPKI/VPKI/VPKI.Web.Client/wwwroot/js/scripts.js +++ b/Projects/VPKI/VPKI/VPKI.Web.Client/wwwroot/js/scripts.js @@ -1,24 +1,17 @@ window.openSaveFileCSV = async function (fileName, writeData) { try { - const handle = await window.showSaveFilePicker({ - suggestedName: fileName, // 파일의 기본 이름 - types: [ - { - description: "csv", - accept: { "text/plain": [".csv" ] } - } - ] - }); + const arrayBuffer = await writeData.arrayBuffer(); + const blob = new Blob([arrayBuffer]); + const url = URL.createObjectURL(blob); - // 파일을 선택한 후 처리 (파일 핸들러) - const writableStream = await handle.createWritable(); - const jsonData = JSON.parse(writeData) + const anchorElement = document.createElement("a"); + anchorElement.href = url; + anchorElement.download = fileName ?? "download.csv"; + anchorElement.click(); - for (var i = 0; i < jsonData.length; i++) { - await writableStream.write(jsonData[i] + "\r\n"); - } - await writableStream.close(); - + anchorElement.remove(); + URL.revokeObjectURL(url); + return true; // 선택된 파일 이름을 반환 } catch (error) { console.error("Error in showSaveFilePicker:", error);