You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server应用读取剪贴板(含图片、文件等)的实现问题

解决Blazor Server中navigator.clipboard.read()返回空数组的问题

1. 权限与触发上下文限制

  • navigator.clipboard.read()要求用户主动交互触发(如按钮点击),浏览器会拦截非用户操作发起的剪贴板请求。Blazor Server基于SignalR通信,务必确保读取剪贴板的代码绑定在用户点击、输入等交互事件中,不能在组件初始化(如OnInitializedAsync)阶段直接调用。
  • 必须在HTTPS环境运行(localhost开发环境除外),否则浏览器会禁用剪贴板API的高级读写能力。

2. 编写专门的JS处理逻辑提取剪贴板数据

直接调用navigator.clipboard.read()返回的ClipboardItem无法直接传递给C#,需要先在JS层解析Blob数据并转换为Base64格式:

在wwwroot/js/clipboard.js中添加处理函数:

window.clipboard = {
    readAll: async function () {
        try {
            const items = await navigator.clipboard.read();
            const result = [];
            for (const item of items) {
                const types = Array.from(item.types);
                for (const type of types) {
                    const blob = await item.getType(type);
                    // 将Blob转为Base64以便C#端接收
                    const base64 = await new Promise(resolve => {
                        const reader = new FileReader();
                        reader.onloadend = () => resolve(reader.result.split(',')[1]);
                        reader.readAsDataURL(blob);
                    });
                    result.push({
                        type: type,
                        data: base64,
                        size: blob.size
                    });
                }
            }
            return result;
        } catch (err) {
            console.error('读取剪贴板失败:', err);
            return [];
        }
    }
};

更新ClipboardService以支持全类型读取:

using Microsoft.JSInterop;
using System.Collections.Generic;
using System.Threading.Tasks;

public sealed class ClipboardService
{
    private readonly IJSRuntime _jsRuntime;

    public ClipboardService(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    public ValueTask<string> ReadTextAsync()
    {
        return _jsRuntime.InvokeAsync<string>("navigator.clipboard.readText");
    }

    public ValueTask WriteTextAsync(string text)
    {
        return _jsRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
    }

    public async Task<List<ClipboardData>> ReadAllAsync()
    {
        return await _jsRuntime.InvokeAsync<List<ClipboardData>>("clipboard.readAll");
    }
}

// 用于接收剪贴板数据的模型类
public class ClipboardData
{
    public string Type { get; set; }
    public string Data { get; set; }
    public long Size { get; set; }
}

3. Blazor组件中正确调用读取方法

确保通过用户交互触发读取操作,示例组件代码:

<button @onclick="ReadClipboardContent">读取剪贴板内容</button>
@if (_clipboardItems != null)
{
    @foreach (var item in _clipboardItems)
    {
        <div>
            <p>类型: @item.Type</p>
            @if (item.Type.StartsWith("image/"))
            {
                <img src="data:@item.Type;base64,@item.Data" style="max-width: 300px;" />
            }
        </div>
    }
}

@code {
    [Inject] private ClipboardService ClipboardService { get; set; }
    private List<ClipboardData> _clipboardItems;

    private async Task ReadClipboardContent()
    {
        _clipboardItems = await ClipboardService.ReadAllAsync();
        StateHasChanged();
    }
}

4. 额外排查点

  • 确认屏幕录制工具是否将实际二进制数据写入剪贴板,部分工具仅写入文件路径而非文件本身,导致read()无法识别。
  • 检查浏览器控制台是否有报错,部分浏览器(如Firefox)需手动开启剪贴板访问权限,或仅在HTTPS环境下支持read()方法。

内容的提问来源于stack exchange,提问作者George Korolev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 01:50:25