Подавать файлы, встроенные в библиотеку .net в HTML в Blazor

.net-standard blazor c# embedded-resource javascript

Вопрос

Я создаю проект Blazor v0.5.1, который использует библиотеку .NET Standard для предоставления всей бизнес-логики. Эта библиотека имеет несколько файлов WAV, хранящихся в виде встроенных ресурсов.

Использование одного из ресурсов в типичной технологии .NET (WinForms, WPF и т. Д.), Которые ссылаются на эту библиотеку, можно сделать следующим образом:

var assemName = "MyLibName";
var assembly = AppDomain
    .CurrentDomain
    .GetAssemblies()
    .First(a => a.GetName().Name == assemName);

//memory stream
var stream = assembly.GetManifestResourceStream($"{assemName}.mysound.wav");

//Can play the file at some point later
var player = new SoundPlayer(stream)
player.Play();

Я хотел бы сделать эквивалент в Blazor. Прямо сейчас, у меня есть звуки, работающие в приложении, копируя / вставляя wav-файлы в wwwroot\sounds проекта, чтобы он служил статическим содержимым HTML. Затем, в JavaScript, я могу играть так:

const audio = new Audio"\sounds\mysound.wave"]);
audio.currentTime = 0;
audio.play();

Но мне бы очень хотелось сделать это, чтобы избежать копирования-вставки и каким-то образом выполнять динамические файлы в качестве этих конечных точек, чтобы он был прозрачным для JS.

Популярные ответы

Ну, я смог это получить. Не уверен, что это лучший способ, но он работает хорошо.

Мне пришлось добавить расширение хранилища Blazor:

https://github.com/BlazorExtensions/Storage

который действует как прокси-сервер для JavaScript SessionStorage и LocalStorage из .NET. После загрузки я добавил каждый встроенный wav-файл из .NET следующим образом:

foreach (var kvp in SoundStreamDictionary)
{
    await sessionStorage.SetItem(
        kvp.Key.ToString().ToLower()  //Key is the name of the sound
        , kvp.Value.ToBase64()  //Value is a Stream object
    );
}

ToBase64 - довольно стандартная обработка потоков .NET:

    public static string ToBase64(this Stream stream)
    {
        byte[] bytes;
        using (var memoryStream = new MemoryStream())
        {
            stream.Position = 0;
            stream.CopyTo(memoryStream);
            bytes = memoryStream.ToArray();
        }

        return Convert.ToBase64String(bytes);
    }

Теперь все данные хранятся в JavaScript SessionStorage как строки. Теперь Trick расшифровывает это на аудио. С помощью этого вспомогательного метода JS (благодаря этому сообщению StackOverflow ):

function b64toBlob(b64Data, contentType, sliceSize) {
    contentType = contentType || '';
    sliceSize = sliceSize || 512;

    const byteCharacters = atob(b64Data);
    const byteArrays = [];

    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        const slice = byteCharacters.slice(offset, offset + sliceSize);

        const byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }

        const byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
    }

    return new Blob(byteArrays, { type: contentType });
}

Поместите это и это в файл JsInterop.js BlazorComponent:

const soundAudios = [];

window.JsSound = {

    loadSounds: function (sounds) {
        sounds.forEach(sound => {
            //Blazor.Storage extension adds extra double quotes so trim
            const str64 = sessionStorage.getItem(sound.path).slice(1, -1);

            const blob = b64toBlob(str64, "audio/wav");
            const blobUrl = URL.createObjectURL(blob);

            const audio = new Audio(blobUrl);
            soundAudios[sound.id] = audio;
        });

        return true;
    },

    play: function (id) {
        const audio = soundAudios[id];
        audio.currentTime = 0;
        audio.play();

        return true;
    },
};

И ПОЛНОСТЬЮ звуки могут быть вызваны по имени из .Net:

private IDictionary<string, int> soundDict = new Dictionary<string, int>();

public Task<string> LoadSounds(IEnumerable<string> fileNames)
{
    var sounds = fileNames
        .Select(name =>
        {
            var snd = new
            {
                id = soundDict.Count,
                path = name
            };
            soundDict.Add(name, snd.id);

            return snd;
        })
        .ToList();

    return JSRuntime.Current.InvokeAsync<string>(
        "JsSound.loadSounds"
        , sounds
    );
}

public Task<string> Play(string name)
{
    return JSRuntime.Current.InvokeAsync<string>(
        "JsSound.play"
        , soundDict[name]
    );
}



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему