在很多上傳文件的應用實例中, 都可以看到[拖放文件到此上傳]這種騷功能 ,今天我們就來試試Blazor能不能完成這個想法. 原文鏈接:https://www.cnblogs.com/densen2014/p/16128246.html 簡述HTML5拖放 拖放是HTML5標準的一部分,任何元素都能夠 ...
在很多上傳文件的應用實例中, 都可以看到[拖放文件到此上傳]這種騷功能 ,今天我們就來試試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();
}
}
}