CKEditor 和 C# Web API,使用简单的上传插件上传图片
Posted
技术标签:
【中文标题】CKEditor 和 C# Web API,使用简单的上传插件上传图片【英文标题】:CKEditor and C# Web API, upload image with simple upload plugin 【发布时间】:2021-12-01 12:44:27 【问题描述】:在我的项目中,我使用 CKEditor WYSWYG 包为我的网站制作 html 内容。 可以插入图片并直接从包发送到服务器。
两天以来,我试图弄清楚如何将发送的图像从 Angular 前端捕获到 Web API,但仍然没有成功。
我将 .Net6 和 Angular 12 与 CKEditor 5 一起使用。
public async Task<ActionResult<string>> AddPostPhoto(IFormFile photo)
try
System.Console.WriteLine(Request.ContentType);
var folderDirectory = $"\\Photos\\PostPhotos";
var path = Path.Combine("Photos/PostPhotos", "fileName.jpg");
var memoryStream = new MemoryStream();
await Request.Body.CopyToAsync(memoryStream);
System.Console.WriteLine(Request.HttpContext.Request.ContentLength);
System.Console.WriteLine(Request.Form.Keys);
if (!Directory.Exists(folderDirectory))
Directory.CreateDirectory(folderDirectory);
await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
memoryStream.WriteTo(fs);
return Ok(new Url = path );
catch(Exception exception)
return BadRequest(exception.Message);
【问题讨论】:
【参考方案1】:我终于找到了一个可行的解决方案。
my-upload-adapter.ts
//ckeditorExComponent class Ends here and MyUploadAdapter class begins here in the same ckeditorEx.ts
export class MyUploadAdapter
xhr: any;
loader: any;
serverUrl: string;
baseApiUrl: string;
constructor(loader: any, serverUrl: string, baseApiUrl: string)
// The file loader instance to use during the upload.
this.loader = loader;
this.serverUrl = serverUrl;
this.baseApiUrl = baseApiUrl;
// Starts the upload process.
upload()
return this.loader.file
.then((file: any) => new Promise((resolve, reject) =>
this._initRequest();
this._initListeners(resolve, reject, file);
this._sendRequest(file);
));
// Aborts the upload process.
abort()
if (this.xhr)
this.xhr.abort();
// Initializes the XMLHttpRequest object using the URL passed to the constructor.
_initRequest()
const xhr = this.xhr = new XMLHttpRequest();
// Note that your request may look different. It is up to you and your editor
// integration to choose the right communication channel. This example uses
// a POST request with JSON as a data structure but your configuration
// could be different.
//Replace below url with your API url
xhr.open('POST', this.baseApiUrl + 'Tutorial/add-post-photo', true);
xhr.responseType = 'json';
// Initializes XMLHttpRequest listeners.
_initListeners(resolve: any, reject: any, file: any)
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = `Couldn't upload file: $file.name.`;
xhr.addEventListener('error', () => reject(genericErrorText));
xhr.addEventListener('abort', () => reject());
xhr.addEventListener('load', () =>
const response = xhr.response;
// This example assumes the XHR server's "response" object will come with
// an "error" which has its own "message" that can be passed to reject()
// in the upload promise.
//
// Your integration may handle upload errors in a different way so make sure
// it is done properly. The reject() function must be called when the upload fails.
if (!response || response.error)
return reject(response && response.error ? response.error.message : genericErrorText);
// If the upload is successful, resolve the upload promise with an object containing
// at least the "default" URL, pointing to the image on the server.
// This URL will be used to display the image in the content. Learn more in the
// UploadAdapter#upload documentation.
resolve(
default: this.serverUrl + response.url
);
);
// Upload progress when it is supported. The file loader has the #uploadTotal and #uploaded
// properties which are used e.g. to display the upload progress bar in the editor
// user interface.
if (xhr.upload)
xhr.upload.addEventListener('progress', (evt: any) =>
if (evt.lengthComputable)
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
);
// Prepares the data and sends the request.
_sendRequest(file: any)
// Prepare the form data.
const data = new FormData();
data.append('upload', file);
// Important note: This is the right place to implement security mechanisms
// like authentication and CSRF protection. For instance, you can use
// XMLHttpRequest.setRequestHeader() to set the request headers containing
// the CSRF token generated earlier by your application.
// Send the request.
this.xhr.send(data);
在 Angular 组件中
onReady($event: any)
$event.plugins.get('FileRepository').createUploadAdapter = (loader: any) =>
return new MyUploadAdapter(loader, this.serverUrl, this.apiUrl);
;
C# Web API 控制器
[HttpPost("add-post-photo")]
public async Task<ActionResult<string>> AddPostPhoto(IFormFile upload)
try
FileInfo fileInfo = new FileInfo(upload.FileName);
System.Console.WriteLine(upload.FileName);
var folderDirectory = $"\\Photos\\PostPhotos";
var path = Path.Combine("Photos\\PostPhotos", upload.FileName);
var memoryStream = new MemoryStream();
await upload.OpenReadStream().CopyToAsync(memoryStream);
if (!Directory.Exists(folderDirectory))
Directory.CreateDirectory(folderDirectory);
await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
memoryStream.WriteTo(fs);
return Ok(new Url = path );
catch(Exception exception)
return BadRequest(exception.Message);
参数上传很重要,否则找不到后端端点
【讨论】:
角度组件中的 onReady 是什么?我正在使用角度 4。以上是关于CKEditor 和 C# Web API,使用简单的上传插件上传图片的主要内容,如果未能解决你的问题,请参考以下文章
在两个应用程序中使用时,ckeditor 未在 IE 中加载
C# Web Api 2 PUT 和 POST 请求“不支持”