Skip to content

Commit 1bf508a

Browse files
committed
Editor增加Upload回调
1 parent 71806c3 commit 1bf508a

3 files changed

Lines changed: 178 additions & 3 deletions

File tree

src/components/BootstrapBlazor.SummerNote/Components/Editor/Editor.razor.cs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ public partial class Editor
6060
[Parameter]
6161
public bool ShowSubmit { get; set; } = true;
6262

63+
/// <summary>
64+
/// 获得/设置 Editor组件内上传文件时回调此方法
65+
/// </summary>
66+
[Parameter]
67+
public Func<EditorUploadFile, Task<string>>? OnFileUpload { get; set; }
68+
6369
private bool _lastShowSubmit = true;
6470

6571
private string? ShowSubmitString => ShowSubmit ? "true" : null;
@@ -83,7 +89,7 @@ public partial class Editor
8389
public string? Language { get; set; }
8490

8591
/// <summary>
86-
/// 获得/设置 语言扩展脚本路径 默认 null 如加载德语可设置为
92+
/// 获得/设置 语言扩展脚本路径 默认 null 如加载德语可设置为
8793
/// </summary>
8894
[Parameter]
8995
public string? LanguageUrl { get; set; }
@@ -186,7 +192,7 @@ protected override async Task InvokeInitAsync()
186192
methodClickPluginItem = nameof(ClickPluginItem);
187193
}
188194

189-
await InvokeVoidAsync("init", Id, Interop, methodGetPluginAttributes, methodClickPluginItem, Height, Value ?? "", Language, LanguageUrl);
195+
await InvokeVoidAsync("init", Id, Interop, methodGetPluginAttributes, methodClickPluginItem, Height, Value ?? "", Language, LanguageUrl, OnFileUpload is not null);
190196
}
191197

192198
/// <summary>
@@ -256,6 +262,35 @@ public async Task<string> ClickPluginItem(string pluginItemName)
256262
return ret;
257263
}
258264

265+
/// <summary>
266+
/// 文件上传回调
267+
/// </summary>
268+
/// <param name="uploadFile"></param>
269+
[JSInvokable]
270+
public async Task<string> ImageUpload(EditorUploadFile uploadFile)
271+
{
272+
#if NET6_0_OR_GREATER
273+
var ret = "";
274+
if (Module != null)
275+
{
276+
var stream = await InvokeAsync<IJSStreamReference>("fetch", Id, uploadFile.Index);
277+
if (stream != null)
278+
{
279+
using var data = await stream.OpenReadStreamAsync();
280+
uploadFile.UploadStream = data;
281+
if (OnFileUpload != null)
282+
{
283+
ret = await OnFileUpload(uploadFile);
284+
}
285+
}
286+
}
287+
return ret;
288+
#else
289+
await Task.Yield();
290+
throw new NotSupportedException();
291+
#endif
292+
}
293+
259294
/// <summary>
260295
/// 执行 editor 的方法
261296
/// </summary>

src/components/BootstrapBlazor.SummerNote/Components/Editor/Editor.razor.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ if (window.BootstrapBlazor === void 0) {
77
window.BootstrapBlazor = {};
88
}
99

10-
export async function init(id, invoker, methodGetPluginAttrs, methodClickPluginItem, height, value, lang, langUrl) {
10+
export async function init(id, invoker, methodGetPluginAttrs, methodClickPluginItem, height, value, lang, langUrl, hasUpload) {
1111
const el = document.getElementById(id)
1212
if (el === null) {
1313
return
@@ -46,6 +46,26 @@ export async function init(id, invoker, methodGetPluginAttrs, methodClickPluginI
4646
const showSubmit = el.getAttribute("data-bb-submit") === "true"
4747
option.toolbar = toolbar;
4848
reloadCallbacks(id, option);
49+
if (hasUpload) {
50+
option.callbacks.onImageUpload = function (files) {
51+
editor.files = files
52+
for (let i = 0; i < files.length; i++) {
53+
const file = files[i];
54+
editor.invoker.invokeMethodAsync('ImageUpload', {
55+
fileName: file.name,
56+
fileSize: file.size,
57+
contentType: file.type,
58+
lastModified: new Date(file.lastModified).toISOString(),
59+
index: i
60+
}).then(data => {
61+
if (data !== "") {
62+
editor.$editor.summernote('insertImage', data, file.name)
63+
}
64+
})
65+
}
66+
}
67+
}
68+
4969
if (!showSubmit) {
5070
const externalOnChange = option.callbacks.onChange;
5171
option.callbacks.onChange = function (contents) {
@@ -146,6 +166,11 @@ export function update(id, val) {
146166
}
147167
}
148168

169+
export function fetch(id, index) {
170+
const md = Data.get(id)
171+
return md.files[index]
172+
}
173+
149174
export function invoke(id, method, parameter) {
150175
const editor = Data.get(id)
151176
editor.$editor.summernote(method, ...parameter)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
// Website: https://www.blazor.zone or https://argozhang.github.io/
4+
5+
namespace BootstrapBlazor.Components;
6+
7+
/// <summary>
8+
/// 文件信息
9+
/// </summary>
10+
public class EditorUploadFile
11+
{
12+
/// <summary>
13+
/// 文件名
14+
/// </summary>
15+
public string? FileName { get; set; }
16+
17+
/// <summary>
18+
/// 文件大小
19+
/// </summary>
20+
public long FileSize { get; set; }
21+
22+
/// <summary>
23+
/// 最后修改日期
24+
/// </summary>
25+
public string? LastModified { get; set; }
26+
27+
/// <summary>
28+
/// 文件类型
29+
/// </summary>
30+
public string? ContentType { get; set; }
31+
32+
/// <summary>
33+
/// 上传的文件流
34+
/// </summary>
35+
public Stream? UploadStream { get; set; }
36+
37+
/// <summary>
38+
/// 文件索引
39+
/// <para>用于标识文件在上传列表中的位置</para>
40+
/// <para>例如在上传多个文件时可以通过此属性区分每个文件的索引位置</para>
41+
/// </summary>
42+
public int Index { get; set; }
43+
44+
/// <summary>
45+
/// 返回码,0为成功,非0失败
46+
/// </summary>
47+
public int Code { get; set; }
48+
49+
/// <summary>
50+
/// 错误信息
51+
/// </summary>
52+
public string? Error { get; set; }
53+
54+
/// <summary>
55+
/// 保存到文件
56+
/// </summary>
57+
/// <param name="fileName"></param>
58+
/// <param name="token"></param>
59+
/// <returns></returns>
60+
public async Task<bool> SaveToFile(string fileName, CancellationToken token = default)
61+
{
62+
var ret = false;
63+
if (UploadStream != null)
64+
{
65+
// 文件保护,如果文件存在则先删除
66+
if (System.IO.File.Exists(fileName))
67+
{
68+
try
69+
{
70+
System.IO.File.Delete(fileName);
71+
}
72+
catch (Exception ex)
73+
{
74+
Code = 1002;
75+
Error = ex.Message;
76+
}
77+
}
78+
79+
var folder = Path.GetDirectoryName(fileName);
80+
if (!string.IsNullOrEmpty(folder) && !Directory.Exists(folder))
81+
{
82+
Directory.CreateDirectory(folder);
83+
}
84+
85+
if (Code == 0)
86+
{
87+
using var uploadFile = File.OpenWrite(fileName);
88+
89+
try
90+
{
91+
// 打开文件流
92+
var stream = UploadStream;
93+
94+
var buffer = new byte[4 * 1096];
95+
int bytesRead = 0;
96+
97+
// 开始读取文件
98+
while ((bytesRead = await stream.ReadAsync(buffer, token)) > 0)
99+
{
100+
await uploadFile.WriteAsync(buffer.AsMemory(0, bytesRead), token);
101+
102+
}
103+
ret = true;
104+
}
105+
catch (Exception ex)
106+
{
107+
Code = 1003;
108+
Error = ex.Message;
109+
}
110+
}
111+
}
112+
return ret;
113+
}
114+
115+
}

0 commit comments

Comments
 (0)