Проблемы с компонентом InputFile в Blazor (серверная часть) .NET 6

Я создал простой компонент Blazor для предварительного просмотра и загрузки изображений. Компонент InputFile скрыт, а метка используется в качестве кнопки для открытия диалогового окна выбора файла. После выбора файла/изображения я хочу показать изображение при предварительном просмотре. Я читаю файл и кодирую его в base64.

@using Microsoft.AspNetCore.Components.Forms
@inject IJSRuntime JSRuntime

<div class = "m-2">        
    <InputFile style = "display: none" id = "productPictureInput" OnChange = "HandleImageUpload" accept = "image/*" />
    <label for = "productPictureInput" class = "btn btn-primary" style = "cursor: pointer;" @onclick = "TriggerFileInput">Add Image</label>
    @if (imagePreviewSrc != null)
    {
        <img src = "@imagePreviewSrc" alt = "Image preview" style = "max-width: 200px; max-height: 200px; margin-left: 10px;" />
    }
</div>

@code {
    private string? imagePreviewSrc;

    private async void TriggerFileInput()
    {
        await JSRuntime.InvokeVoidAsync( "triggerClickEvent", "productPictureInput" );
    }

    private async void HandleImageUpload(InputFileChangeEventArgs e)
    {
        var imageFile = e.GetMultipleFiles().FirstOrDefault();
        if (imageFile != null)
        {
            var imageStream = imageFile.OpenReadStream();
            var buffer = new byte[imageStream.Length];
            await imageStream.ReadAsync(buffer);
            imagePreviewSrc = $"data:image/jpg;base64,{Convert.ToBase64String(buffer)}";
            StateHasChanged();
        }
    }
}

Когда я пробую компонент на другой странице Blazor, я наблюдаю странное поведение. Диалог загрузки (выбора файла) открывается дважды, изображение загружается только частично (см. прикрепленное изображение), и затем я не могу изменить (выбрать другое) изображение.

Итак, пожалуйста, подскажите мне, что происходит не так? Спасибо.

JS-функция:

function triggerClickEvent(elementId) {
    document.getElementById(elementId).click();
}

Возможно, важно упомянуть: это приложение ASP.NET MVC, .NET 6. Я добавил services.AddServerSideBlazor(); в Startup.cs.

Здравствуйте, во-первых, я предлагаю вам использовать эту библиотеку для входного файла от Microsoft fluentui-blazor.net/InputFile она неплохая, не нужно изобретать велосипед. Вторая запись файла в формате base64 и установка пути к нему могут привести к ошибкам. Что такое разрешение изображения? Существует предел того, насколько большим может быть изображение, передаваемое таким образом.

Artur Chrzanowski 07.07.2024 12:40

Используете ли вы этот компонент InputFile? Learn.microsoft.com/en-us/aspnet/core/blazor/…

Tiny Wang 08.07.2024 08:57

Вы не предоставили метод для triggerClickEvent, но боюсь, что он используется для запуска диалогового окна загрузки файла. И это может быть проблемой, поскольку я тестировал <Inputfile />, который работал хорошо.

Tiny Wang 08.07.2024 09:44

Да, я использую указанный вами компонент InputFile.

max 08.07.2024 14:57
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
90
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я использовал код ниже, который работал хорошо.

@page "/Input"
@rendermode InteractiveServer

<h3>Inputfile Preview</h3>
<div class = "m-2">        
    <InputFile OnChange = "@HandleImageUpload" multiple accept = "image/*" />
    @if (imagePreviewSrc != null)
    {
        <img src = "@imagePreviewSrc" alt = "Image preview" style = "max-width: 200px; max-height: 200px; margin-left: 10px;" />
    }
</div>

@code {
    private string? imagePreviewSrc;

    private async void HandleImageUpload(InputFileChangeEventArgs e)
    {
        var imageFile = e.GetMultipleFiles().FirstOrDefault();
        if (imageFile != null)
        {
            var imageStream = imageFile.OpenReadStream();
            var buffer = new byte[imageStream.Length];
            await imageStream.ReadAsync(buffer);
            imagePreviewSrc = $"data:image/jpg;base64,{Convert.ToBase64String(buffer)}";
            StateHasChanged();
        }
    }
}

Затем я использовал этот компонент в другом компоненте, он тоже работал хорошо.

Боюсь, Load (choose file) dialog opens twice,and then I cannot change это из-за кода JS, которым вы не поделились. Не могли бы вы поделиться кодом JS и тем, как вы использовали этот компонент в другом компоненте? И image is only partly loaded (see attached image) может быть связано с CSS

Tiny Wang 08.07.2024 09:49

Зачем вам включать множественную загрузку, а затем брать только первый файл?

Bennyboy1973 08.07.2024 12:48

Скопировал фрагмент кода из официального документа и забыл удалить атрибут multipe. Моя вина, и я возьму только первый файл - коды из фрагмента кода ОП.

Tiny Wang 08.07.2024 17:01

Я создал новое веб-приложение Blazor (серверная часть, .NET 8) и добавил код, но получил тот же результат:

@page "/input"
@rendermode InteractiveServer

<h3>Inputfile Preview</h3>
<div class = "m-2">
    <InputFile OnChange = "@HandleImageUpload" multiple accept = "image/*" />
    @if (imagePreviewSrc != null)
    {
        <img src = "@imagePreviewSrc" alt = "Image preview" style = "max-width: 200px; max-height: 200px; margin-left: 10px;" />
    }
</div>

@code {
    private string? imagePreviewSrc;

    private async void HandleImageUpload(InputFileChangeEventArgs e)
    {
        var imageFile = e.GetMultipleFiles().FirstOrDefault();
        if (imageFile != null)
        {
            var imageStream = imageFile.OpenReadStream();
            var buffer = new byte[imageStream.Length];
            await imageStream.ReadAsync(buffer);
            imagePreviewSrc = $"data:image/jpg;base64,{Convert.ToBase64String(buffer)}";
            StateHasChanged();
        }
    }
}

Пробовал Гугл Хром и Оперу. Одно изображение было загружено и показано правильно. Другие нет.

Когда я посмотрел на код элемента (изображения) в браузере, я увидел, что код base64 имеет «AAAAAAAAAAAAAAAAAAAA», начиная с 15% и до конца.

I tried Google Chrome and Opera. One image was loaded and shown correctly. Others not. --> Это значит, что один из браузеров работал хорошо? Или одно изображение хорошее, а два нет?
Tiny Wang 09.07.2024 03:53

Это означает, что одно изображение хорошее, а два — нет.

max 09.07.2024 16:47

Когда я посмотрел на код элемента (изображения) в браузере, я увидел, что код base64 имеет «AAAAAAAAAAAAAAAAAA» примерно до 15% и до конца.

В этой статье Загрузка файлов ASP.NET Core Blazor сказано, что SignalR имеет максимальный размер сообщения 32 КБ, и поэтому файлы обрезаются. Я пытался увеличить размер в Program.cs, но это не помогло.

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddHubOptions( options => options.MaximumReceiveMessageSize = 1024 * 1024 * 10);

Привет, я нашел этот раздел, который может быть рекомендован Microsoft для загрузки изображений и предварительного просмотра. Learn.microsoft.com/en-us/aspnet/core/blazor/…

Tiny Wang 10.07.2024 04:11

Этот пример работает для меня.

max 10.07.2024 15:05
Ответ принят как подходящий

Чтобы избежать повторного открытия диалогового окна выбора файла, нам просто нужно добавить PreventDefault:

    <label for = "productPictureInput" class = "btn btn-primary" style = "cursor: pointer;"
           @onclick = "TriggerFileInput" @onclick:preventDefault = "true">Add Image</label>

Другие вопросы по теме