在很多上传文件的应用实例中, 都可以看到[拖放文件到此上传]这种骚功能 ,今天我们就来试试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>

代码

  1. InputFile 开启 multiple ,接受多文件上传
  2. 使用JS隔离技术
  3. 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/

项目源码

Github | Gitee

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

最新文章

  1. Oracle 11g RAC 卸载CRS步骤
  2. QTP操作excel文档
  3. 9 DelayQueueEntry 延时队列节点类——Live555源码阅读(一)基本组件类
  4. Mango DS Training #48 ---线段树2 解题手记
  5. POJ 3411 Paid Roads(DFS)
  6. Selenium - IDE模式匹配
  7. 8-13-Exercise
  8. 提高你30%的设计效率的PPT快捷键
  9. fckeditor使用详解
  10. TCP/IP之三次握手、四次挥手
  11. 看到关于socket非阻塞模式设置方式记录一下。
  12. 关于百度地图API (持续跟新)
  13. Spring Boot快速入门
  14. SpringMVC格式转化错误之HTTP Status [400] – [Bad Request]
  15. 分享基于 websocket 网页端聊天室
  16. oracle学习笔记(六) JDBC使用
  17. A1126. Eulerian Path
  18. 将 java 改写成 beanshell 的经验之谈
  19. [原][qt]解决qt在vs下could not find or load the Qt platform plugin &quot;windows&quot; in &quot;&quot;问题
  20. spring boot 配置数据源

热门文章

  1. Java UDP 编程
  2. 在微信小程序中使用 echarts 图片-例 折线图
  3. 关于 Linux Polkit 权限提升漏洞(CVE-2021-4034)的修复方法
  4. 给windows右键添加快捷启动程序
  5. mybatis学习一:基于xml与注解配置入门实例与问题
  6. 面试问题之C++语言:volatile关键字的作用
  7. Java 中的同步集合与并发集合有什么区别?
  8. 有哪些类型的通知(Advice)?
  9. 说说 Redis 哈希槽的概念?
  10. java的API