经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTML/CSS » 浏览器 » 查看文章
Blazor 拖放上传文件转换格式并推送到浏览器下载
来源:cnblogs  作者:AlexChow  时间:2023/2/17 10:01:11  对本文有异议

前言

昨天有个小伙伴发了一个老外java编写的小工具给我,功能是转换西班牙邮局快递Coreeos express的单据格式成Amazon格式,他的需求是改一下程序为匹配转换另一个快递公司MRW格式到Amazon格式,然而我堂堂一个Blazor发烧友,怎么可能去反编译人家的java修改呢?必须直接撸一个Blazor的啊.

实现目标

拖放多文件上传, 不落地(无中间保存临时文件)直接内存流转换格式, 直接推送弹出下载文件.

分析需求

原始MRW文件.txt

  1. "Abonado","Depto.","Fecha","N. Envio","N. Lote","Tipo de Cobro","Bultos","Kg.","Imp Reemb.","Referencia","Destinatario","Direccion","C.P.","Poblacion","Pais","Servicio","Retorno Alb.",""
  2. "xxx SL ","N/A","15/02/2023","0263608650029","02636xxx20230214204409","Pagados","1","1","","403-6273741-3115504","Antonia xxx FERNANDEZ","C/MENDEZ NU?EZ 222","06420","CASTUERA","ESPA?A","U19E--Urgente 19 Expedición","SinRetorno",""
  3. "xxx SL ","N/A","15/02/2023","0263608650028","02636xxx20230214204409","Pagados","1","1","","406-8908494-9500324","Baris xxx","Parque Erreniega Parkea,","31180","CIZUR MAYOR","ESPA?A","U19E--Urgente 19 Expedición","SinRetorno",""

实体类

来源

  1. public class MrwTicket
  2. {
  3. public string Abonado { get; set; }
  4. [DisplayName("Depto.")]
  5. public string Depto { get; set; }
  6. public DateTime Fecha { get; set; }
  7. [DisplayName("N. Envio")]
  8. public string N_Envio { get; set; }
  9. [DisplayName("N. Lote")]
  10. public string N_Lote { get; set; }
  11. [DisplayName("Tipo de Cobro")]
  12. public string TipoDeCobro { get; set; }
  13. public string Bultos { get; set; }
  14. [DisplayName("Kg.")]
  15. public string Kg { get; set; }
  16. [DisplayName("Imp Reemb.")]
  17. public string ImpReemb { get; set; }
  18. public string Referencia { get; set; }
  19. public string Destinatario { get; set; }
  20. public string Direccion { get; set; }
  21. [DisplayName("C.P.")]
  22. public string CP { get; set; }
  23. public string Poblacion { get; set; }
  24. public string Pais { get; set; }
  25. public string Servicio { get; set; }
  26. [DisplayName("Retorno Alb.")]
  27. public string RetornoAlb { get; set; }
  28. }

转换目标

  1. public class AmazonTicket
  2. {
  3. [DisplayName("order-id")]
  4. public string Order_id { get; set; }
  5. [DisplayName("order-item-id")]
  6. public string Order_item_id { get; set; }
  7. [DisplayName("quantity")]
  8. public string Quantity { get; set; }
  9. [DisplayName("ship-date")]
  10. public string Ship_date { get; set; }
  11. [DisplayName("carrier-code")]
  12. public string Carrier_code { get; set; }
  13. [DisplayName("carrier-name")]
  14. public string Carrier_name { get; set; }
  15. [DisplayName("tracking-number")]
  16. public string Tracking_number { get; set; }
  17. [DisplayName("ship-method")]
  18. public string Ship_method { get; set; }
  19. }

建立Blazor页面 Mrw2Amazon.razor

拖放上传可以参考往期文章 https://www.cnblogs.com/densen2014/p/16128246.html

组件UI

  1. @page "/Mrw2Amazon"
  2. @inherits PublicComponentsBase
  3. @namespace AmeBlazor.Components
  4. <h4>MRW txt Amazon txt</h4>
  5. <PageTitle>MRW txt Amazon txt</PageTitle>
  6. <div @ref="UploadElement" style="padding: 20px; width: 200px; height: 200px; background-color: cornflowerblue; border: 2px dashed #0087F7; border-radius: 5px; ">
  7. <p>拖放上传文件</p>
  8. <InputFile OnChange="OnChange" class="form-control" multiple @ref="inputFile" />
  9. </div>
  10. <pre>
  11. <code>
  12. @uploadstatus
  13. </code>
  14. </pre>

拖放上传js文件 wwwroot/drag.js

  1. export function init(wrapper, element, inputFile) {
  2. //阻止浏览器默认行为
  3. document.addEventListener("dragleave", function (e) {
  4. e.preventDefault();
  5. }, false);
  6. document.addEventListener("drop", function (e) {
  7. e.preventDefault();
  8. }, false);
  9. document.addEventListener("dragenter", function (e) {
  10. e.preventDefault();
  11. }, false);
  12. document.addEventListener("dragover", function (e) {
  13. e.preventDefault();
  14. }, false);
  15. element.addEventListener("drop", function (e) {
  16. try {
  17. var fileList = e.dataTransfer.files; //获取文件对象
  18. //检测是否是拖拽文件到页面的操作
  19. if (fileList.length == 0) {
  20. return false;
  21. }
  22. inputFile.files = e.dataTransfer.files;
  23. const event = new Event('change', { bubbles: true });
  24. inputFile.dispatchEvent(event);
  25. }
  26. catch (e) {
  27. wrapper.invokeMethodAsync('DropAlert', e);
  28. }
  29. }, false);
  30. element.addEventListener('paste', function (e) {
  31. inputFile.files = e.clipboardData.files;
  32. const event = new Event('change', { bubbles: true });
  33. inputFile.dispatchEvent(event);
  34. }, false);
  35. return {
  36. dispose: () => {
  37. element.removeEventListener('dragleave', onDragLeave);
  38. element.removeEventListener("drop", onDrop);
  39. element.removeEventListener('dragenter', onDragHover);
  40. element.removeEventListener('dragover', onDragHover);
  41. element.removeEventListener('paste', handler);
  42. }
  43. }
  44. }

下载功能

Pages\_Layout.cshtml < /body >之前添加js代码

  1. <script>
  2. window.downloadFileFromStream = async (fileName, contentStreamReference) => {
  3. const arrayBuffer = await contentStreamReference.arrayBuffer();
  4. const blob = new Blob([arrayBuffer]);
  5. const url = URL.createObjectURL(blob);
  6. const anchorElement = document.createElement('a');
  7. anchorElement.href = url;
  8. anchorElement.download = fileName ?? '';
  9. anchorElement.click();
  10. anchorElement.remove();
  11. URL.revokeObjectURL(url);
  12. }
  13. </script>

组件代码Mrw2Amazon.razor.cs

先拉个库MiniExcel

<PackageReference Include="MiniExcel" Version="1.*" />

  1. 动态加载 drag.js 文件.(参考往期文章,js隔离 https://www.cnblogs.com/densen2014/p/16027851.html)
  2. 使用拖放读取到 IBrowserFile 文件流
  3. 转换为 MemoryStream 供给 MiniExcel 读取. (PS:不能直接使用 IBrowserFile 的 stream , 当作课后作业自己了解一下.)
  4. MiniExcel 读取格式: var mrwTicket = MiniExcel.Query(fs, excelType: ExcelType.CSV).ToList();
  5. 转换格式
  6. 另存为目标格式csv
  7. 直接弹出目标文件下载到浏览器
  8. 全程不落地
  1. using Microsoft.AspNetCore.Components;
  2. using Microsoft.AspNetCore.Components.Forms;
  3. using Microsoft.JSInterop;
  4. using MiniExcelLibs;
  5. using MiniExcelLibs.Csv;
  6. public partial class Mrw2Amazon : IAsyncDisposable
  7. {
  8. [Inject]
  9. IJSRuntime JS { get; set; }
  10. //既然不落地,那就不需要这些了
  11. //[Inject]
  12. //protected Microsoft.AspNetCore.Hosting.IWebHostEnvironment HostEnvironment { get; set; }
  13. protected ElementReference UploadElement { get; set; }
  14. protected InputFile? inputFile { get; set; }
  15. private DotNetObjectReference<Mrw2Amazon>? wrapper;
  16. private IJSObjectReference? module;
  17. private IJSObjectReference? dropInstance;
  18. //既然不落地,那就不需要这些了
  19. //protected string UploadPath = "";
  20. protected string? uploadstatus;
  21. long maxFileSize = 1024 * 1024 * 15;
  22. //既然不落地,那就不需要这些了
  23. //protected override void OnAfterRender(bool firstRender)
  24. //{
  25. //if (!firstRender) return;
  26. //UploadPath = Path.Combine(HostEnvironment!.WebRootPath, "uploads", "temp"); //初始化上传路径
  27. //if (!Directory.Exists(UploadPath)) Directory.CreateDirectory(UploadPath); //不存在则新建目录
  28. //}
  29. protected async Task OnChange(InputFileChangeEventArgs e)
  30. {
  31. int i = 0;
  32. var selectedFiles = e.GetMultipleFiles(100);
  33. foreach (var item in selectedFiles)
  34. {
  35. i++;
  36. await OnSubmit(item);
  37. uploadstatus += Environment.NewLine + $"[{i}]: " + item.Name;
  38. }
  39. }
  40. protected async Task OnSubmit(IBrowserFile efile)
  41. {
  42. try
  43. {
  44. if (efile == null) return;
  45. if (efile.ContentType != "text/plain")
  46. {
  47. uploadstatus += Environment.NewLine + $"只接受txt文件.{efile.Name}为{efile.ContentType}";
  48. return;
  49. }
  50. await using var fs = new MemoryStream();
  51. using var stream = efile.OpenReadStream(maxFileSize);
  52. await stream.CopyToAsync(fs);
  53. var mrwTicket = MiniExcel.Query<MrwTicket>(fs, excelType: ExcelType.CSV).ToList();
  54. var amazonTicket = new List<AmazonTicket>();
  55. foreach (var item2 in mrwTicket)
  56. {
  57. amazonTicket.Add(new AmazonTicket()
  58. {
  59. Order_id = item2.Referencia,
  60. Ship_date = item2.Fecha.ToString("MM-dd-yyyy"),
  61. Carrier_code = "MRW",
  62. Tracking_number = item2.N_Envio.Remove(5, 1),
  63. Ship_method = "Urgente 19",
  64. });
  65. }
  66. var memoryStream = new MemoryStream();
  67. memoryStream.SaveAs(amazonTicket, excelType: ExcelType.CSV, configuration: new CsvConfiguration() { Seperator = '\t' });
  68. memoryStream.Seek(0, SeekOrigin.Begin);
  69. using var streamRef = new DotNetStreamReference(stream: memoryStream);
  70. await JS.InvokeVoidAsync("downloadFileFromStream", Path.GetFileNameWithoutExtension(efile.Name) + "_amazon.txt", streamRef);
  71. uploadstatus += Environment.NewLine + $"{efile.Name} 转换OK";
  72. }
  73. catch (Exception e)
  74. {
  75. uploadstatus += Environment.NewLine + $"转换出错 {e.Message}";
  76. }
  77. StateHasChanged();
  78. }
  79. protected override async Task OnAfterRenderAsync(bool firstRender)
  80. {
  81. if (!firstRender) return;
  82. module = await JS.InvokeAsync<IJSObjectReference>("import", "./drag.js");
  83. wrapper = DotNetObjectReference.Create(this);
  84. dropInstance = await module.InvokeAsync<IJSObjectReference>("init", wrapper, UploadElement, inputFile!.Element);
  85. }
  86. [JSInvokable]
  87. public void DropAlert(string msg)
  88. {
  89. uploadstatus += Environment.NewLine + $"[!Alert!]: " + msg;
  90. StateHasChanged();
  91. }
  92. async ValueTask IAsyncDisposable.DisposeAsync()
  93. {
  94. if (dropInstance != null)
  95. {
  96. await dropInstance.InvokeVoidAsync("dispose");
  97. await dropInstance.DisposeAsync();
  98. }
  99. if (wrapper != null)
  100. {
  101. wrapper.Dispose();
  102. }
  103. if (module != null)
  104. {
  105. await module.DisposeAsync();
  106. }
  107. }
  108. }

运行

可接受多文件拖放同时转换

完整代码来的,直接cv应该可以用了.

原文链接:https://www.cnblogs.com/densen2014/p/17125416.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号