Blazor 使用拖放(drag and drop)上传文件
在很多上传文件的应用实例中, 都可以看到[拖放文件到此上传]这种骚功能 ,今天我们就来试试Blazor能不能完成这个想法.
原文链接:https://www.cnblogs.com/densen2014/p/16128246.html
简述HTML5拖放
拖放是HTML5标准的一部分,任何元素都能够拖放,也能够将本地的文件拖放到页面上。
设置元素可拖放
为了使元素可拖动,把 draggable 属性设置为 true
<img draggable="true" />
拖放事件
有7个拖放事件可以捕获,如下:
dragstart:开始拖元素触发
dragenter:元素拖进可drop元素(绑定drop事件的元素)时触发
dragover:当元素拖动到drop元素上时触发
drop:当元素放下到drop元素触发
dragleave :当元素离开drop元素时触发
drag:每次元素被拖动时会触发
dragend:放开拖动元素时触发
完成一次拖放的事件过程是: dragstart –> dragenter –> dragover –> drop –> dragend
浏览器支持
Edge、Firefox、Opera 12、Chrome 以及 Safari 5 支持拖放。
拖拽上传实现
1.新建工程n02drag,将项目添加到解决方案中
dotnet new blazorserver -o n02drag
dotnet sln add n02drag/n02drag.csproj
2.在文件夹wwwroot/lib,添加drag子文件夹,新建app.js文件
先阻止页面默认的拖放行为,不然页面会被拖放的文件替换了。
//阻止浏览器默认行为
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);
设置drop区域
当文件拖放到drop区域时,就能触发上传。
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);
2.在文件Pages/Index.razor,添加上传组件
页面
@implements IAsyncDisposable
@inject IJSRuntime JS
<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>
代码
- InputFile 开启 multiple ,接受多文件上传
- 使用JS隔离技术
- Dispose处理回收
@code{
[Inject] protected Microsoft.AspNetCore.Hosting.IWebHostEnvironment? HostEnvironment { get; set; } //获取IWebHostEnvironment
protected ElementReference UploadElement { get; set; }
protected InputFile? inputFile { get; set; }
private DotNetObjectReference<Index>? 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, "Upload"); //初始化上传路径
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)
{
if (efile == null) return;
var tempfilename = Path.Combine(UploadPath, efile.Name);
await using FileStream fs = new(tempfilename, FileMode.Create);
using var stream = efile.OpenReadStream(maxFileSize);
await stream.CopyToAsync(fs);
StateHasChanged();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender) return;
module = await JS.InvokeAsync<IJSObjectReference>("import", "./lib/drag/app.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();
}
}
}
3.就这么简单吗?我们还可以加上一些骚功能 粘贴文件上传
element.addEventListener('paste', function (e) {
inputFile.files = e.clipboardData.files;
const event = new Event('change', { bubbles: true });
inputFile.dispatchEvent(event);
}, false);
4.限制传输格式
*时间有限,js部分同学们自己完成吧,这里是InputFile 上限制一下
<div style="padding-top:40px; padding: 20px; width: 200px; height: 200px; background-color: cornflowerblue; border: 2px dashed #0087F7; border-radius: 5px; ">
上传图片
<InputFile OnChange="OnChange" style="max-width: 400px" class="form-control" multiple accept='image/*' />
</div>
5.完整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);
}
}
}
参考资料
用20行代码实现文件上传,浏览目录功能 (Blazor server) https://github.com/densen2014/Blazor100/wiki/9.-用20行代码实现文件上传,浏览目录功能-(Blazor-server)
HTML5拖放(drag and drop)与plupload的懒人上传 https://www.programminghunter.com/article/31061232701/
项目源码
知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。
Blazor 使用拖放(drag and drop)上传文件的更多相关文章
- 上传文件 file upload 学习笔记
这里我只会说说一些完成 file upload 的基础 API. 很多项目我们需要上传文件. 有简单的 input file, 有需要验证的,有需要压缩的(img),有需要分段的(video),有需要 ...
- 原生API实现拖拽上传文件实践
功能: 拖拽上传文件.图片,上传的进度条,能够同时上传多个文件. 完整的demo地址:https://github.com/qcer/FE-Components/tree/master/QDrag 涉 ...
- Sharepoint 2010 无法上传文件的问题
现象: 用户拥有某文档库的参与讨论权限,但是点击“上传文件”时,系统提示当前用户没有权限 (Access Denied) . 某用户拥有某文档库的参与讨论权限,“上传单个文件”按键是可以用的,但是“上 ...
- 【Bootstrap】bootstrap-fileinput上传文件插件
[bootstrap-fileinput] 这是个据传最好用的bootstrap相关联的文件上传控件,支持拖曳上传,多线程上传,上传文件预览等等功能. 首先还是说一下要引入的一些文件: <lin ...
- js实现分段上传文件
使用js实现分段上传文件,本文使用了FileReader对象,可参考:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader 1)获取文 ...
- ajax上传文件及进度显示
之前在博文:原生ajax写法就提及过ajax2.0与1.0的差别是多了FormData和利用FormData文件上传(当然还有跨域,但不是本文的重点). 那么具体怎么样实现ajax上传文件呢? 一般来 ...
- layui上传文件配合进度条
首先看一下效果图: 修改layui的源文件upload.js 1.打开layui/modules/upload.js 2.搜索ajax 3.找到url: 4.添加以下代码: ,xhr:l.xhr(fu ...
- Vue上传文件:ElementUI中的upload实现
一.上传文件实现 两种实现方式: 1.直接action <el-upload .利用before-upload属性 此种方式有个弊端,就是action是必选的参数,那么action如果和pos ...
- java-上传文件与现实上传文件
项目结构: 项目展示: 数据库: /* SQLyog Ultimate v12.09 (64 bit) MySQL - 5.5.53 : Database - fileupload ********* ...
随机推荐
- WPF中Enter 焦点转移方法
1.Set the TabIndex="16"2. private void detailGrid_Keydown(object sender, KeyEventArgs e) { ...
- Java将彩色PDF转为灰度
本文以Java代码为例介绍如何实现将彩色PDF文件转为灰度(黑白)的PDF文件,即:将PDF文档里面的彩色图片或者文字等通过调用PdfGrayConverter.toGrayPdf()方法转为文档页面 ...
- 前端知识之BOM和DOM
前端基础之BOM和DOM windw对象 指浏览器窗口,所有的浏览器都支持window对象 常用的window方法 window.innerHeight 浏览器窗口的内部高度 window.inner ...
- C++设计模式 - 命令模式(Command)
行为变化模式 在组件的构建过程中,组件行为的变化经常导致组件本身剧烈的变化."行为变化" 模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合. 典型模 ...
- Spring---Spring专题(二)
1.Spring配置数据源 1.1 数据源(连接池)的作用 数据源(连接池)是提高程序性能而出现的 事先实例化数据源,初始化部分链接资源 使用连接资源时从数据源中获取 使用完毕后将连接资源归还给数据源 ...
- vue3.0的更新和defineProperty优化?
放弃 Object.defineProperty ,使用更快的原生 Proxy (访问对象拦截器, 也成代理器) 提速, 降低内存使用, Tree-shaking更友好 支持IE11等 使用Types ...
- websocket使用nginx代理后连接频繁打开和关闭
前几天开发了一个功能,使用websocket向前台发送消息,与前端联调时一切正常,但是发布到环境出现如下报错: 发现404,无法找到连接,突然想到环境上是走nginx代理的,应该是nginx没有配置代 ...
- 转载:TCP协议如何保证可靠传输
转载至:https://www.cnblogs.com/xiaokang01/p/10033267.html TCP协议如何保证可靠传输 概述: TCP协议保证数据传输可靠性的方式主要有: (校 序 ...
- Redis 集群的主从复制模型是怎样的?
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所 以集群使用了主从复制模型,每个节点都会有 N-1 个复制品.
- 什么是HTML 5?
HTML 5是HTML的新标准,其主要目标是无需任何额外的插件如Flash.Silverlight等,就可以传输所有内容.它囊括了动画.视频.丰富的图形用户界面等. HTML5是由万维网联盟(W3C) ...