如何在Angular中实现CKEditor5并将图像上传到ASP.NET Core Web API?

有关在Angular中CkEditor5的详细实现以及在ASP.NET Core中上传图片的信息,请参见我的答案

iso0921 回答:如何在Angular中实现CKEditor5并将图像上传到ASP.NET Core Web API?

可能的错误:

  

未捕获(承诺):TypeError:无法读取CKEditor中未定义的属性“ data-ck-expando”

上述错误的解决方案:

remove all the code in polyfill.ts and add below code

 import 'zone.js/dist/zone.js';  // Included with Angular CLI.
 (window as any).__Zone_disable_toString = true;

在软件包下方安装

npm install --save @ckeditor/ckeditor5-angular

安装其中一个官方编辑器版本或创建自定义版本。

假设您选择了@ ckeditor / ckeditor5-build-classic:

npm install --save @ckeditor/ckeditor5-build-classic

现在,将CKEditorModule添加到您的应用程序模块导入中:

import { CKEditorModule } from '@ckeditor/ckeditor5-angular';

@NgModule( {    

imports: [        

CKEditorModule,// ...    ],// ... } )

ckeditorEx.html:

  <ckeditor  [config]="editorConfig" [editor]="Editor" [(ngModel)]="description"

  #desc="ngModel" spellcheck="false" required minlength="50" name="editor5" (ready)="onReady($event)">

ckeditorEx.ts

  

查找此URL并指向您的api URL   xhr.open('POST','https://www.example.com/api/articles/CkEditorUploads',true);

import { Component,OnInit } from '@angular/core';

import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';

@Component({

 selector: 'app-ckeditorEx',templateUrl: './ckeditorEx.component.html',styleUrls: ['./ckeditorEx.component.css']

})



export class ckeditorExComponent implements OnInit {



 public Editor = ClassicEditor;

 editorConfig = {

   placeholder: 'Type here..',};

 description: any;



 constructor() {

   }



 ngOnInit() {

   }



 onReady($event) {

   $event.plugins.get('FileRepository').createUploadAdapter = (loader) => {

     return new MyUploadAdapter(loader);

   };

 }

//ckeditorExComponent class Ends here and MyUploadAdapter class begins here in the same ckeditorEx.ts

class MyUploadAdapter {

 xhr: any;

 loader: any;

 constructor(loader) {

   // The file loader instance to use during the upload.

   this.loader = loader;

 }



 // Starts the upload process.

 upload() {

   return this.loader.file

     .then(file => 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','https://www.example.com/api/articles/CkEditorUploads',true);

   xhr.responseType = 'json';

 }



 // Initializes XMLHttpRequest listeners.

 _initListeners(resolve,file) {

   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: 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 => {

       if (evt.lengthComputable) {

         loader.uploadTotal = evt.total;

         loader.uploaded = evt.loaded;

       }

     });

   }

 }



 // Prepares the data and sends the request.

 _sendRequest(file) {

   // 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);

 }

}

ASP.NET Web API

 Controller Constructor:

         // Import host in your controller cconstructor like below

          private readonly IHostingEnvironment host;



          public ExampleController(

           ..........................

           IHostingEnvironment host)

           {

               this.host = host;

            }

    Controller Method:

           [AllowAnonymous]

           [HttpPost("CkEditorUploads2")]

          // Don't change "IFormFile upload" text below.

           public async Task<IActionResult> UploadImage(IFormFile upload)

           {

               var file = upload;

               var allowedExtensions = new[] {

                ".Jpg",".png",".PNG",".JPG","JPEG",".jpg",".jpeg",".Heif",".tiff"

                };

               if (file == null) return BadRequest("Null file");

               if (file.Length > 10 * 1024 * 1024) return BadRequest("Max file size exceeded.");

               if (file.Length == 0) return BadRequest("Empty file");

               var fileName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);

               var uploadsFolderPath = Path.Combine(host.WebRootPath,"uploads");

               if (!Directory.Exists(uploadsFolderPath))

                   Directory.CreateDirectory(uploadsFolderPath);

               var ext = Path.GetExtension(file.FileName);

               // if (allowedExtensions.fin(ext)) return BadRequest("Invalid Image type.");

               var filePath = Path.Combine(uploadsFolderPath,fileName);

               using (var stream = new FileStream(filePath,FileMode.Create))

               {

                   await file.CopyToAsync(stream);

               }

              // Converting to EST timezone

               var timeUtc = DateTime.UtcNow;

               TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

               DateTime easternTime = TimeZoneInfo.ConvertTime(timeUtc,easternZone);

               var editorID = Guid.NewGuid().ToString();

               var editorImages = new editorImages

               {

                   id = editorID,url = "https://example.com/uploads/" + fileName,Logintime = easternTime,fileName = fileName,};

               // Save the image details to your database

               ArticlesRepository.saveEditorImagesInfo(editorImages);

               await unitofWork.Complete();

               var res = await ArticlesRepository.getEdiorImagebyID(editorID);

               if (res == null)

                // Important to send return the result in this format

                   return NotFound(new

                   {

                       uploaded = false,error = "Could not upload this image"

                   });

               // Important to send return the result in this format

               return Ok(new

               {

                   uploaded = true,//return imagelocation

                   url = res.url

               });

           }
本文链接:https://www.f2er.com/3068667.html

大家都在问