fix(s22): 1C-CSV detect charset из Content-Type + UpdatedAt в migration
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
- Parse1cCsv ловил Windows-1251 на UTF-8 bodies без BOM. Теперь смотрит Content-Type charset первым, потом BOM, потом WIN-1251. - Migration Phase22a_OrgExports забыл UpdatedAt колонку (Entity base имеет её). ADD COLUMN IF NOT EXISTS внутри миграции для уже созданных таблиц. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
4c1ac37a08
commit
1af4290313
|
|
@ -574,33 +574,40 @@ public record OneCImportResponse(int Created, int Skipped, IReadOnlyList<CsvImpo
|
|||
return new OneCImportResponse(v.Created, rows.Count - v.Created, v.Errors, v.Ids);
|
||||
}
|
||||
|
||||
/// <summary>Детект кодировки: BOM UTF-8 → utf-8; иначе предполагаем
|
||||
/// Windows-1251 (стандарт 1С). После чтения первых байтов перематываем
|
||||
/// поток в начало.</summary>
|
||||
private static System.Text.Encoding DetectEncoding(Stream s)
|
||||
/// <summary>Детект кодировки: 1) Content-Type charset (если указан),
|
||||
/// 2) BOM UTF-8 — utf-8, 3) fallback Windows-1251 (стандарт 1С).
|
||||
/// После чтения первых байтов перематываем поток в начало.</summary>
|
||||
private System.Text.Encoding DetectEncoding(Stream s)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Регистрируем codepage providers (Windows-1251 не в default-пуле .NET 8).
|
||||
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
||||
}
|
||||
try { System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); }
|
||||
catch { /* идемпотентно */ }
|
||||
if (!s.CanSeek)
|
||||
return new System.Text.UTF8Encoding(true);
|
||||
|
||||
// 1. Content-Type charset.
|
||||
var ct = Request.ContentType;
|
||||
if (!string.IsNullOrEmpty(ct))
|
||||
{
|
||||
var m = System.Text.RegularExpressions.Regex.Match(ct, @"charset=([^;\s]+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
if (m.Success)
|
||||
{
|
||||
try { return System.Text.Encoding.GetEncoding(m.Groups[1].Value); }
|
||||
catch { /* fall through */ }
|
||||
}
|
||||
}
|
||||
|
||||
// 2. BOM-based detect.
|
||||
if (s.CanSeek)
|
||||
{
|
||||
var pos = s.Position;
|
||||
var buf = new byte[3];
|
||||
var n = s.Read(buf, 0, 3);
|
||||
s.Position = pos;
|
||||
if (n >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
|
||||
return System.Text.Encoding.UTF8;
|
||||
try
|
||||
{
|
||||
return System.Text.Encoding.GetEncoding("windows-1251");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return System.Text.Encoding.UTF8;
|
||||
}
|
||||
|
||||
// 3. Fallback — Windows-1251 (стандарт 1С).
|
||||
try { return System.Text.Encoding.GetEncoding("windows-1251"); }
|
||||
catch { return System.Text.Encoding.UTF8; }
|
||||
}
|
||||
|
||||
/// <summary>Парсер 1С-CSV → CsvProductRow. Возвращает (rows, errors).
|
||||
|
|
|
|||
|
|
@ -30,9 +30,15 @@ protected override void Up(MigrationBuilder b)
|
|||
""DownloadTokenExpiresAt"" timestamp with time zone NULL,
|
||||
""NotifyEmail"" varchar(200) NULL,
|
||||
""Error"" varchar(2000) NULL,
|
||||
""CreatedAt"" timestamp with time zone NOT NULL DEFAULT now()
|
||||
""CreatedAt"" timestamp with time zone NOT NULL DEFAULT now(),
|
||||
""UpdatedAt"" timestamp with time zone NULL
|
||||
);
|
||||
|
||||
-- Идемпотентно — для случая когда таблица уже создана без UpdatedAt
|
||||
-- (миграция была запущена до её добавления в схему).
|
||||
ALTER TABLE public.org_exports
|
||||
ADD COLUMN IF NOT EXISTS ""UpdatedAt"" timestamp with time zone NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ""IX_org_exports_Org_CreatedAt""
|
||||
ON public.org_exports (""OrganizationId"", ""CreatedAt"" DESC);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ""IX_org_exports_DownloadToken""
|
||||
|
|
|
|||
Loading…
Reference in a new issue