簡體   English   中英

如何使用 Blazor 上傳文件?

[英]How do I upload files with Blazor?

我找到了BlazorInputFile庫,但從 2019 年 10 月起仍有未打開的 PR,我不確定該庫是否仍在維護。 另外,我在博客中發現了幾篇關於我們如何在 Blazor 中使用 JS 上傳文件的文章。 雖然如果可能的話我不想使用 JS,但我確實需要使用 Blazor 上傳文件......是否可以在不使用 JavaScript 的情況下這樣做?

為像我這樣仍在尋找在 Blazor 中上傳文件的最佳方式的人回答這個問題。 我也在嘗試安裝SteveSandersonMS 的 repo ,然后意識到截至 2021 年 2 月,ASP.NET Core 5.0 中實際上有一個本機InputFile組件。

它支持在 Blazor 中上傳單個和多個文件,並且易於使用。 (而且您不需要添加自己的 js 文件等)

我將它用於單個文件上傳 - 您需要做的就是在 Razor 頁面中添加InputFile組件:

<InputFile OnChange="@SingleUpload" />

然后在我的情況下,我需要字節數組中的文件:

@code {

   private async Task SingleUpload(InputFileChangeEventArgs e)
   {
       MemoryStream ms = new MemoryStream();
       await e.File.OpenReadStream().CopyToAsync(ms);
       var bytes = ms.ToArray();
       //do something with bytes
   }
}

InputFileChangeEventArgs為您提供了IBrowserFileIReadOnlyList ,您可以使用它來獲取NameLastModifiedSizeContentType ,以及用於獲取StreamOpenReadStream方法。

希望這會有所幫助,關於如何在ASP.NET 文檔中獲取多個文件有很好的文檔和代碼

編輯:您還需要添加System.IO命名空間:

@using Sytem.IO

,謝謝沒有。

截至 2020 年 6 月,假設您使用表單的最佳方法 (WA) 是使用Tewr 的FileReader。 讓我們從 API 開始,post 控制器是:

      public async Task<IActionResult> PostMedia(
        [FromForm] IFormFile Picture,
        [FromForm] string Focus,
        [FromForm] string ID,
        [FromForm] string Title,
        [FromForm] string FormType,
        [FromForm] string AnimalType,
        [FromForm] string Mode,
        [FromForm] string AnimalID
        )
    {
        Debug.WriteLine($"-------------------------------------{Focus}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{ID}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{Title}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{FormType}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{AnimalType}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{Mode}-----------------------------------------------");
        Debug.WriteLine($"-------------------------------------{AnimalID}-----------------------------------------------");


        //check if file was fully uploaded
        if (Picture.Length == 0 || Picture == null)

            return BadRequest("Upload a new File");
        else
            return Ok ("do something with this data....") 
     }

那么客戶端的 post 方法將是:

    public async Task PostFile()
  {
    //create content headers
    var content = new MultipartFormDataContent();
    content.Headers.ContentDisposition = new 
    System.Net.Http.Headers.ContentDispositionHeaderValue("form-data");

    //create content
    content.Add(new StreamContent(Pic.Stream, (int)Pic.Stream.Length), "Picture", Pic.FileName);
    content.Add(new StringContent(Pic.Title), "Title");
    content.Add(new StringContent(Pic.Focus), "Focus");
    content.Add(new StringContent(Pic.ID), "ID");
    content.Add(new StringContent(Pic.FormType), "FormType");
    content.Add(new StringContent(Pic.AnimalType), "AnimalType");
    content.Add(new StringContent(Pic.Mode), "Mode");
    content.Add(new StringContent(Pic.AnimalID), "AnimalID");
    //call to the server
    var upload = await Http.PostAsync("Media",content);

    //get server response
    Pic.Message = await upload.Content.ReadAsStringAsync();
   }

Tewr 文件閱讀器可幫助您將文件讀入流中,在我的情況下,該流被傳遞給 Pic 對象。 綁定到表單中輸入元素的 onchange 的閱讀功能將是:

  public async Task ReadFile()
   {
    var file = (await fileReaderService.CreateReference(Xelement).EnumerateFilesAsync()).FirstOrDefault();

    if (file == null)  return;


    var fileInfo = await file.ReadFileInfoAsync();

    Pic.FileName = fileInfo.Name;


    // Read into RAM
    using (var memoryStream = await file.CreateMemoryStreamAsync((int)fileInfo.Size))
    {
        // Copy store image into pic object
        Pic.Stream = new MemoryStream(memoryStream.ToArray());
    }

}

請注意,Xelement 是 ElementReference,它用作表單中輸入元素的引用。

我通過使用一個組件和一些 javascript(看起來像一個按鈕)來做到這一點。 一旦組件和 js 合並,你就再也不用擔心了……

這是上傳組件 (Upload.Razor):

 @inject IJSRuntime JSRuntime @if (AllowMulitple) { <input id="Xinputfile00" type="file" accept="@Filter" @onchange="UploadFile" multiple hidden /> } else { <input id="Xinputfile00" type="file" accept="@Filter" @onchange="UploadFile" hidden /> } <button class="btn btn-default" @onclick="ClickUpload">@Title</button> @code { [Parameter] public FileData[] Files { get; set; } [Parameter] public string Filter { get; set; } [Parameter] public string Title { get; set; } [Parameter] public bool AllowMulitple { get; set; } [Parameter] public Action Uploaded { get; set; } async Task UploadFile() { string[] result = await JSRuntime.InvokeAsync<string[]>("blazorExtensions.GetFileData", "Xinputfile00"); List<FileData> results = new List<FileData>(); foreach (string file in result) { results.Add(new FileData(file)); } this.Files = results.ToArray(); if (Uploaded != null) { Uploaded(); } } async Task ClickUpload() { await JSRuntime.InvokeVoidAsync("blazorExtensions.InvokeClick", "Xinputfile00"); } public class FileData { public string Base64 { get; set; } public string MIMEType { get; set; } public byte[] Bytes { get { return Convert.FromBase64String(this.Base64); } } public FileData(string data) { if (string.IsNullOrWhiteSpace(data) || !data.Contains(",")) { return; } string[] alldata = data.Split(','); this.MIMEType = alldata[0].Remove(0, 5).Replace(";base64", ""); this.Base64 = alldata[1]; } }

這是javascript摘錄:

 window.blazorExtensions = { GetFileData: async function (id) { var target = document.getElementById(id); var filesArray = Array.prototype.slice.call(target.files); return Promise.all(filesArray.map(window.blazorExtensions.fileToDataURL)); }, fileToDataURL: async function (file) { var reader = new FileReader(); return new Promise(function (resolve, reject) { reader.onerror = function () { reader.abort(); reject(new DOMException('Error occurred reading file ' + file)); }; reader.onload = function (event) { resolve(reader.result); console.log('resolved'); }; reader.readAsDataURL(file); console.log('returned'); }) }, InvokeClick: function (id) { var elem = document.getElementById(id); if (typeof elem.onclick == "function") { elem.onclick.apply(elem); } elem.click(); }, }

這是一個調用標記示例:

 <Upload @ref="upload" Filter=".xlsx" Title="Upload" AllowMulitple="false" Uploaded="DoMyExcelThingOrSomething" />

以及上傳后調用的方法:

    Upload upload;
    void DoMyExcelThingOrSomething()
{
    if (upload.Files.Length < 1 || string.IsNullOrWhiteSpace(upload.Files[0].Base64))
    {
        //...nothing good here...
        return;
    }
    //play with upload.Files here...
}

在目前的情況下(截至 2020 年 4 月 2 日),您將需要 JS,這是不可避免的。

您可以采取兩種主要方法:

  • 在輸入的onchange事件中獲取文件數據,並通過將byte[]傳遞給 C# 方法來調用 C# 方法 - 這基本上是您鏈接的文件選擇器方法,您可以在 Blazor 應用程序中獲取文件數據以執行任何您想做的事情.

  • 在輸入的onchange事件中獲取文件數據,並使用 JS 調用將接收文件並對其進行處理的遠程端點(例如將其保存在您的 NAS 上或將其放入您的數據庫中)。 這是一個實際的文件上傳,而不是文件選擇器。

從編碼的角度來看,這兩種方法都是相似的——你需要 JS。 也許在 Blazor 的未來版本中,我們將獲得一個<InputFile>來進行選擇,以便您可以使用 C# HTTP 請求上傳。

文件選擇器方法相對容易實現(字面意思是幾行),但它不會在服務器上為您提供文件,您必須為此付出一些努力。 文件上傳方法更難做到正確。 我個人會使用別人的包。 對於文件上傳,Blazor 的 Telerik UI 之類的東西可能適合商業用途,對於更簡單的選擇器,已經有另一個鏈接示例的答案。 順便說一下,Telerik 的演示也有一個這樣的例子,作為為一些演示實現的組件。

對於 Blazor 服務器,以下將文件上傳到服務器。 無需單獨的 API 服務器,也無需使用 JS 代碼。 並將 stream 轉換為文件。

@using System.IO
@inject IWebHostEnvironment env

@*for ibrowser*@
@using Microsoft.AspNetCore.Components.Forms;

<h1>Blazor Server File Upload</h1>

<h3>@Message</h3>

<form @onsubmit="OnSubmit">
    <InputFile OnChange="OnInputFileChange" multiple />
    <br /><br />
    <button type="submit">Upload Selected File(s)</button>
</form>

@code {
    string Message = "No file(s) selected";
    IReadOnlyList<IBrowserFile> selectedFiles;

    void OnInputFileChange(InputFileChangeEventArgs e)
    {
        selectedFiles = e.GetMultipleFiles();
        Message = $"{selectedFiles.Count} file(s) selected";
        this.StateHasChanged();
    }

    async void OnSubmit()
    {
        foreach (var file in selectedFiles)
        {
            Stream stream = file.OpenReadStream();
            var path = $"{env.WebRootPath}\\{file.Name}";
            FileStream fs = File.Create(path);
            await stream.CopyToAsync(fs);
            stream.Close();
            fs.Close();
        }
        Message = $"{selectedFiles.Count} file(s)   uploaded on server";
        this.StateHasChanged();
    }
}

http 的小幅編輯://www.bipinjoshi.net/articles/06473cc7-a391-409e-948d-3752ba3b4a6c.aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM