Blazor 拖放上传文件转换格式并推送到浏览器下载

Posted AlexChow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Blazor 拖放上传文件转换格式并推送到浏览器下载相关的知识,希望对你有一定的参考价值。

前言

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

分析需求

原始MRW文件.txt

"Abonado","Depto.","Fecha","N. Envio","N. Lote","Tipo de Cobro","Bultos","Kg.","Imp Reemb.","Referencia","Destinatario","Direccion","C.P.","Poblacion","Pais","Servicio","Retorno Alb.",""
"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",""
"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",""

实体类

来源

  public class MrwTicket
    
        public string Abonado  get; set; 

        [DisplayName("Depto.")]
        public string Depto  get; set; 

        public DateTime Fecha  get; set; 

        [DisplayName("N. Envio")]
        public string N_Envio  get; set; 

        [DisplayName("N. Lote")]
        public string N_Lote  get; set; 

        [DisplayName("Tipo de Cobro")]
        public string TipoDeCobro  get; set; 

        public string Bultos  get; set; 

        [DisplayName("Kg.")]
        public string Kg  get; set; 

        [DisplayName("Imp Reemb.")]
        public string ImpReemb  get; set; 


        public string Referencia  get; set; 


        public string Destinatario  get; set; 


        public string Direccion  get; set; 

        [DisplayName("C.P.")]
        public string CP  get; set; 

        public string Poblacion  get; set; 

        public string Pais  get; set; 

        public string Servicio  get; set; 

        [DisplayName("Retorno Alb.")]
        public string RetornoAlb  get; set; 
    

转换目标

    public class AmazonTicket
    

        [DisplayName("order-id")]
        public string Order_id  get; set; 

        [DisplayName("order-item-id")]
        public string Order_item_id  get; set; 

        [DisplayName("quantity")]
        public string Quantity  get; set; 

        [DisplayName("ship-date")]
        public string Ship_date  get; set; 

        [DisplayName("carrier-code")]
        public string Carrier_code  get; set; 

        [DisplayName("carrier-name")]
        public string Carrier_name  get; set; 

        [DisplayName("tracking-number")]
        public string Tracking_number  get; set; 

        [DisplayName("ship-method")]
        public string Ship_method  get; set; 

    

建立Blazor页面 Mrw2Amazon.razor

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

组件UI

@page "/Mrw2Amazon"
@inherits PublicComponentsBase
@namespace AmeBlazor.Components

<h4>MRW txt 转 Amazon txt</h4>

<PageTitle>MRW txt 转 Amazon txt</PageTitle>

<div @ref="UploadElement" >
    <p>拖放上传文件</p>
    <InputFile OnChange="OnChange" class="form-control" multiple @ref="inputFile" />
</div>

<pre>
<code>
        @uploadstatus
</code>
</pre>

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

export function init(wrapper, element, inputFile) 

    //阻止浏览器默认行为
    document.addEventListener("dragleave", function (e) 
        e.preventDefault();
    , false);
    document.addEventListener("drop", function (e) 
        e.preventDefault();
    , false);
    document.addEventListener("dragenter", function (e) 
        e.preventDefault();
    , false);
    document.addEventListener("dragover", function (e) 
        e.preventDefault();
    , false); 

    element.addEventListener("drop", function (e) 

        try 
            var fileList = e.dataTransfer.files; //获取文件对象
            //检测是否是拖拽文件到页面的操作
            if (fileList.length == 0) 
                return false;
            

            inputFile.files = e.dataTransfer.files;
            const event = new Event(\'change\',  bubbles: true );
            inputFile.dispatchEvent(event);
        
        catch (e) 
            wrapper.invokeMethodAsync(\'DropAlert\', e);
        
    , false);

    element.addEventListener(\'paste\', function (e) 
    
        inputFile.files = e.clipboardData.files;
        const event = new Event(\'change\',  bubbles: true );
        inputFile.dispatchEvent(event);
    , false);

    return 
        dispose: () => 
            element.removeEventListener(\'dragleave\', onDragLeave);
            element.removeEventListener("drop", onDrop);
            element.removeEventListener(\'dragenter\', onDragHover);
            element.removeEventListener(\'dragover\', onDragHover);
            element.removeEventListener(\'paste\', handler);
        
    

下载功能

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

    <script>
        window.downloadFileFromStream = async (fileName, contentStreamReference) => 
            const arrayBuffer = await contentStreamReference.arrayBuffer();
            const blob = new Blob([arrayBuffer]);
            const url = URL.createObjectURL(blob);
            const anchorElement = document.createElement(\'a\');
            anchorElement.href = url;
            anchorElement.download = fileName ?? \'\';
            anchorElement.click();
            anchorElement.remove();
            URL.revokeObjectURL(url);
        
    </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. 直接弹出目标文件下载到浏览器
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.JSInterop;
using MiniExcelLibs;
using MiniExcelLibs.Csv;

    public partial class Mrw2Amazon : IAsyncDisposable
    

        [Inject]
        IJSRuntime JS  get; set; 

        [Inject] 
        protected Microsoft.AspNetCore.Hosting.IWebHostEnvironment HostEnvironment  get; set; 

        protected ElementReference UploadElement  get; set; 
        protected InputFile? inputFile  get; set; 

        private DotNetObjectReference<Mrw2Amazon>? wrapper;

        private IJSObjectReference? module;
        private IJSObjectReference? dropInstance;

        protected string UploadPath = "";
        protected string? uploadstatus;
        long maxFileSize = 1024 * 1024 * 15;

        protected override void OnAfterRender(bool firstRender)
        
            if (!firstRender) return;
            UploadPath = Path.Combine(HostEnvironment!.WebRootPath, "uploads", "temp"); //初始化上传路径
            if (!Directory.Exists(UploadPath)) Directory.CreateDirectory(UploadPath); //不存在则新建目录
        

        protected async Task OnChange(InputFileChangeEventArgs e)
        
            int i = 0;
            var selectedFiles = e.GetMultipleFiles(100);
            foreach (var item in selectedFiles)
            
                i++;
                await OnSubmit(item);
                uploadstatus += Environment.NewLine + $"[i]: " + item.Name;
            
        

        protected async Task OnSubmit(IBrowserFile efile)
        
            try
            

            if (efile == null) return;
            if (efile.ContentType != "text/plain")
            
                uploadstatus += Environment.NewLine + $"只接受txt文件.efile.Name为efile.ContentType";
                return;
            
            await using var fs = new MemoryStream();
            using var stream = efile.OpenReadStream(maxFileSize);

            await stream.CopyToAsync(fs);

            var mrwTicket = MiniExcel.Query<MrwTicket>(fs, excelType: ExcelType.CSV).ToList();
            var amazonTicket = new List<AmazonTicket>();
            foreach (var item2 in mrwTicket)
            
                amazonTicket.Add(new AmazonTicket()
                
                    Order_id = item2.Referencia,
                    Ship_date = item2.Fecha.ToString("MM-dd-yyyy"),
                    Carrier_code = "MRW",
                    Tracking_number = item2.N_Envio.Remove(5, 1),
                    Ship_method = "Urgente 19",
                );
            

            var memoryStream = new MemoryStream();
            memoryStream.SaveAs(amazonTicket, excelType: ExcelType.CSV, configuration: new CsvConfiguration()  Seperator = \'\\t\' );
            memoryStream.Seek(0, SeekOrigin.Begin);
            using var streamRef = new DotNetStreamReference(stream: memoryStream);

            await JS.InvokeVoidAsync("downloadFileFromStream", Path.GetFileNameWithoutExtension(efile.Name) + "_amazon.txt", streamRef);

            uploadstatus += Environment.NewLine + $"efile.Name 转换OK";

            
            catch (Exception e)
            
                uploadstatus += Environment.NewLine + $"转换出错 e.Message";
            
            StateHasChanged();
        


        protected override async Task OnAfterRenderAsync(bool firstRender)
        
            if (!firstRender) return;

            module = await JS.InvokeAsync<IJSObjectReference>("import", "./drag.js");
            wrapper = DotNetObjectReference.Create(this);
            dropInstance = await module.InvokeAsync<IJSObjectReference>("init", wrapper, UploadElement, inputFile!.Element);
        

        [JSInvokable]
        public void DropAlert(string msg)
        
            uploadstatus += Environment.NewLine + $"[!Alert!]: " + msg;
            StateHasChanged();
        


        async ValueTask IAsyncDisposable.DisposeAsync()
        
            if (dropInstance != null)
            
                await dropInstance.InvokeVoidAsync("dispose");
                await dropInstance.DisposeAsync();
            

            if (wrapper != null)
            
                wrapper.Dispose();
            

            if (module != null)
            
                await module.DisposeAsync();
            
        

    

运行

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

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

以上是关于Blazor 拖放上传文件转换格式并推送到浏览器下载的主要内容,如果未能解决你的问题,请参考以下文章

从外部附件输入流中读取并推送到 s3 的最有效方法?

免费开源Blazor在线Ico转换工具

git 初始化本地项目并推送到远程

在 Web 应用程序中接收数据并推送到客户端浏览器的套接字

将提交的文件拆分并推送到两个不同的分支

搜索处于活动状态并推送到下一个视图控制器时出现导航栏问题