ckeditor 5中的图像上传不适用于laravel 8

Posted

技术标签:

【中文标题】ckeditor 5中的图像上传不适用于laravel 8【英文标题】:image upload in ckeditor 5 not working with laravel 8 【发布时间】:2021-04-25 09:48:21 【问题描述】:

我正在使用 Laravel 8 和 javascript 开发一个网站。 我使用ckeditor 5,它工作正常。当我尝试上传照片时出现问题。照片上传完成,但我收到一条错误消息并且没有显示照片。我收到以下标题的错误: “无法上传文件:filename.jpg” 我想我没有向前端返回正确的响应。 我在 route/web.php 文件中有这些代码

Route::group(["middleware"=>"auth","prefix"=>"panel"],function ()
    Route::post('/post/edit/post_slug', [PostController::class,"update"])->name("updatePostRoute");
    Route::get('/post/edit/post_slug', [RenderPanelController::class,"renderPostEditPage"])->name("renderPostEditPageRoute");
    Route::post('/post/ckeditor/upload', [PostController::class,"upload_image_cke"])->name('ckeditor.upload');
);

在 PostController 中

    public function upload_image_cke(Request $request)
        if ($request->hasFile('upload')) 
            $originName = $request->file('upload')->getClientOriginalName();
            $fileName = pathinfo($originName, PATHINFO_FILENAME);
            $extension = $request->file('upload')->getClientOriginalExtension();
            $fileName = $fileName . '_' . time() . '.' . $extension;

            $request->file('upload')->move(public_path('media'), $fileName);

            $CKEditorFuncNum = $request->input('CKEditorFuncNum');
            $url = asset('media/' . $fileName);
            $msg = 'upload successfully';
            $response = "<script>window.parent.CKEDITOR.tools.callFunction($CKEditorFuncNum, '$url', '$msg')</script>";

            @header('Content-type: text/html; charset=utf-8');
            echo $response;

        
    

在刀片文件中:

<textarea type="text" class="form-control" name="content" id="content"></textarea>
<meta name="csrf-token" content=" csrf_token() ">

<script src="https://cdn.ckeditor.com/ckeditor5/27.1.0/classic/ckeditor.js"></script>

<script>
    ClassicEditor
        .create( document.querySelector( '#content' ), 
            ckfinder: 
                uploadUrl: 'route('ckeditor.upload')."?command=QuickUpload&type=Files&responseType=json"',
                headers: 
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
                
            
        ,
            alignment: 
                options: [ 'right', 'right' ]
             )
        .then( editor => 
            console.log( editor );
        )
        .catch( error => 
            console.error( error );
        )
</script>

我需要返回什么响应才能使照片上传正常工作?

【问题讨论】:

【参考方案1】:

我有另一种方法。希望它适用于您和许多开发者。

我的做法是为每个用户动态定义一个存储路径($path_url 变量)

请注意,您必须在终端上运行php artisan storage:link

web.php

Route::post('ckeditor/upload', 'App\Http\Controllers\CKEditorController@store')->name('ckeditor.upload');

CKEditorController - 方法存储

public function store(Request $request)
   
      $path_url = 'storage/' . Auth::id();

      if ($request->hasFile('upload')) 
         $originName = $request->file('upload')->getClientOriginalName();
         $fileName = pathinfo($originName, PATHINFO_FILENAME);
         $extension = $request->file('upload')->getClientOriginalExtension();
         $fileName = Str::slug($fileName) . '_' . time() . '.' . $extension;
         $request->file('upload')->move(public_path($path_url), $fileName);
         $url = asset($path_url . '/' . $fileName);
      

      return response()->json(['url' => $url]);
   

表格

<textarea name="body" id="body" class="form-control"></textarea>

现在,您必须定义一个“适配器”来将文件上传到存储

<script src="https://cdn.ckeditor.com/ckeditor5/27.1.0/classic/ckeditor.js"></script>
<script>
    //Define an adapter to upload the files
    class MyUploadAdapter 
       constructor(loader) 
          // The file loader instance to use during the upload. It sounds scary but do not
          // worry — the loader will be passed into the adapter later on in this guide.
          this.loader = loader;

          // URL where to send files.
          this.url = ' route('ckeditor.upload') ';

          //
       
       // 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.
          // xhr.open('POST', this.url, true);
          xhr.open("POST", this.url, true);
          xhr.setRequestHeader("x-csrf-token", " csrf_token() ");
          xhr.responseType = "json";
       
       // Initializes XMLHttpRequest listeners.
       _initListeners(resolve, reject, 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);
       
       // ...
    

    function SimpleUploadAdapterPlugin(editor) 
       editor.plugins.get("FileRepository").createUploadAdapter = (loader) => 
          // Configure the URL to the upload script in your back-end here!
          return new MyUploadAdapter(loader);
       ;
    

    //Initialize the ckeditor
    ClassicEditor.create(document.querySelector("#body"), 
       extraPlugins: [SimpleUploadAdapterPlugin],
    ).catch((error) => 
       console.error(error);
    );

</script>

我希望我有所帮助。一个拥抱!

【讨论】:

$url = Storage::url($request->file('upload')->store('public/uploads'));【参考方案2】:

在 PostController 中

public function upload_image_cke(Request $request)
    if ($request->hasFile('upload')) 
        $originName = $request->file('upload')->getClientOriginalName();
        $fileName = pathinfo($originName, PATHINFO_FILENAME);
        $extension = $request->file('upload')->getClientOriginalExtension();
        $fileName = $fileName . '_' . time() . '.' . $extension;

        $request->file('upload')->move(public_path('media'), $fileName);

        $url = asset('media/' . $fileName);
        return response()->json(['fileName' => $fileName, 'uploaded'=> 1, 'url' => $url]);
        

    

在刀片文件中:

<script>
    ClassicEditor
        .create( document.querySelector( '#content' ), 
            ckfinder: 
                uploadUrl: 'route('ckeditor.upload').'?_token='.csrf_token()'
            
        ,
            alignment: 
                options: [ 'right', 'right' ]
             )
        .then( editor => 
            console.log( editor );
        )
        .catch( error => 
            console.error( error );
        )
</script>

【讨论】:

以上是关于ckeditor 5中的图像上传不适用于laravel 8的主要内容,如果未能解决你的问题,请参考以下文章

使用 CKEditor CDN 时如何从桌面上传 CKEditor 中的图像?

如何在 CKEditor 5 中启用图像上传支持?

ckeditor_uploader动态图像上传路径

“ng2-CKEditor”节点模块不适用于打字稿[Angular2]

文件上传选项以从相机拍摄图像或从图库中选择不适用于 Mozilla Firefox 中的 Web 应用程序

简单上传ckeditor 5 无法上传文件:未定义