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" style="padding: 20px; width: 200px; height: 200px; background-color: cornflowerblue; border: 2px dashed #0087F7; border-radius: 5px; ">
<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.*" />
- 动态加载 drag.js 文件.(参考往期文章,js隔离 https://www.cnblogs.com/densen2014/p/16027851.html)
- 使用拖放读取到 IBrowserFile 文件流
- 转换为 MemoryStream 供给 MiniExcel 读取. (PS:不能直接使用 IBrowserFile 的 stream , 当作课后作业自己了解一下.)
- MiniExcel 读取格式: var mrwTicket = MiniExcel.Query(fs, excelType: ExcelType.CSV).ToList();
- 转换格式
- 另存为目标格式csv
- 直接弹出目标文件下载到浏览器
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 拖放上传文件转换格式并推送到浏览器下载的更多相关文章
- $Django ajax简介 ajax简单数据交互,上传文件(form-data格式数据),Json数据格式交互
一.ajax 1 什么是ajax:异步的JavaScript和xml,跟后台交互,都用json 2 ajax干啥用的?前后端做数据交互: 3 之前学的跟后台做交互的方式: -第一种:在浏览器 ...
- 上传文件Base64格式(React)
记录一下上传文件时将文件数据转为Base64的方法 通过 FileReader对象创建一个实例,然后使用 readAsDataURL方法将数据转为Base64格式 注意: 读取过程是异步的 绑定onl ...
- js jquery验证上传文件的格式和大小
// 验证附件格式和大小 function confirmData() { var flag = true; var message = ""; var errorSize = & ...
- ajaxsubmit 上传文件 在IE中返回的内容 提示下载文件
在ajaxSubmit提交表单的时候,如果表单内有文件上传的话,会判断参数是否配置的iframe为false参数,如果没有,会用创建隐藏iframe方式提交表单,如果设定了iframe为false,则 ...
- Qt通过HTTP POST上传文件(python做服务端,附下载)
本文使用Qt Creator用HTTP POST的方法上传文件,并给出一个上传文件的例程. 本文主要客户端,所以对于服务器端程序编写的描述会比较简略 服务器使用Django编写,django服务器接收 ...
- 上传文件到 Sharepoint 的文档库中和下载 Sharepoint 的文档库的文件到客户端
文件操作应用场景: 如果你的.NET项目是运行在SharePoint服务器上的,你可以直接使用SharePoint服务器端对象模型,用SPFileCollection.Add方法 http://msd ...
- 上传文件时,Request报文头不同浏览器会产生不同的content-type
选择一个zip文件上传,用IE看的报文头是image/jpeg,用chrom看是application/octet-stream. 第一次遇到这个类型的content-type,百度了一下, octe ...
- IE浏览器上传文件后返回结果会自动弹出下载框
服务器使用的是node,其它语言的后台没测试过. 在IE低版本浏览器下,当你上传一个文件后后台会返回一些数据,但是IE浏览器会弹出下载提示. 这个问题是之前处理的了,没有细究,今天有人问到这个问题,顺 ...
- input[type=file]上传文件(格式判断、文件大小、上传成功后操作)
var isUploadImg = false; //在input file内容改变的时候触发事件******************上传图片 $('#filed').change(function( ...
- 吴裕雄--天生自然 PHP开发学习:本地PHPSTORM在线连接、编辑、上传文件到虚拟机,并在本地浏览器运行(前提是虚拟机与本机已桥连成功)
随机推荐
- 2022-11-09 Acwing每日一题
本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...
- Inventor 2021保姆级安装教程
Inventor 2021 WIN10 64位安装步骤: 1.先使用"百度网盘客户端"下载INT21_CN_x64安装包到电脑磁盘里,并鼠标右击进行解压缩,安装前先断网,然后找到I ...
- 【Docker】容器使用规范--安全挂载建议
容器挂载过程和安全挂载建议 绑定挂载 本文所提到的挂载主要指绑定挂载(bind mount),即通过-v /xx/xx:/xx/xx 和 --mount type=bind,xxx,xxx两种方式设置 ...
- leetcode学习记录2.13
[13] 罗马数字转整数 import java.util.HashMap; import java.util.Map; /* * * [13] 罗马数字转整数 * * https://leetcod ...
- oracle 中模糊查询对like的代替insrt()函数 可以做到效率节约一倍以上
昨天在处理一个字符拆分的功能时,用用到了insrt()函数,偶然发现其实特可以代替模糊查询的like,经多次测试可节约效率一倍以上. 代码如下: select distinct(a.deptname) ...
- 【PPT】NET Conf China 2022,主题:C#在iNeuOS工业互联网操作系统的开发及应用
从技术生态发展过程及理念.产品级解决方案理念.产品系统框架及主要功能介绍.产品系统二次开发和应用案例等5个方面进行了主题发言. 从2003到现在,使用.NET技术生态19年左右. 10多年的煤炭.电 ...
- 《MySQL必知必会》之快速入门游标和触发器
第二十四章 使用游标 本章将介绍什么是游标以及如何使用游标 游标 之前的select语句检索出来的数据,没有办法得到第一行或者下一行 有时,需要在检索出来的行中前进或后退一行或多行.这就是使用游标的原 ...
- RocketMQ Schema——让消息成为流动的结构化数据
本文作者:许奕斌,阿里云智能高级研发工程师. Why we need schema RocketMQ 目前对于消息体没有任何数据格式的约束,可以是 JSON ,可以是对象 toString ,也可以只 ...
- python 小球碰撞游戏
#小球和挡板要自己找照片,放在一个单独文件夹,音乐也是一样的import pygame pygame.init()#游戏资源加载 a = 700#x轴为700 b = 800#y抽为800 sceee ...
- Maven多模块管理
项目的目录结构: 一.创建父工程的必须遵循以下两点: 1.packaging标签的文本内容必须设置为pom 1 <?xml version="1.0" encoding=&q ...