ckeditor / ckeditor5-angular

Official CKEditor 5 Angular 5+ component.
https://ckeditor.com/ckeditor-5
Other
205 stars 111 forks source link

Error when Upload Image with UploadAdapter #273

Open babbler-eu opened 3 years ago

babbler-eu commented 3 years ago

Unhandled Promise rejection: t is not a constructor ; Zone: ; Task: Promise.then ; Value: TypeError: t is not a constructor I get this error when I try to compile after creating personal uploadadapter This is my code public editorConfig = { placeholder: 'Type the content here ...', extraPlugins: [ (editor: any) => { return this.imagePluginFactory(editor) } ] }; public imagePluginFactory(editor: any): void { editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader: any ) => { return new UploadAdapter( 'http://localhost/server/upload_image.php', loader ); }; }

this is my Upload Adapter

`export class UploadAdapter { public loader: any; public xhr: XMLHttpRequest; public urlPath: string;

    constructor(  urlPath: string, loader: any ) {

        this.loader = loader;
        this.urlPath = urlPath;
        this.xhr = new XMLHttpRequest();
    }

    upload() {
        var _this3 = this;

        return this.loader.file.then(function (file: string | Blob) {
          return new Promise(function (resolve, reject) {
            var fd = new FormData();
            _this3.xhr.open('POST', _this3.urlPath, true);
            _this3.xhr.upload.addEventListener('progress', function (e) {
              _this3.loader.uploadTotal = 100;
              _this3.loader.uploaded = Math.round(e.loaded * 100 / e.total);
            }); 

            _this3.xhr.onreadystatechange = function () {

             if (_this3.xhr.readyState === 4 && _this3.xhr.status === 200) {

                var response = JSON.parse(_this3.xhr.responseText);
                //console.log(response);
                var images = {
                  "default": response.url
                };
                resolve(images);
              } else if (_this3.xhr.status !== 200) {
                reject('Upload failed');

              }

            }; 
            fd.append('file', file);

            _this3.xhr.send(fd);
          });
        });
      } }`

this is my php

`<?php header('Access-Control-Allow-Origin: *');

$base_dir = $_SERVER['DOCUMENT_ROOT'];
$base_host = "http://localhost"; $base_dir_img = $base_dir."/server/image/"; $base_host_img = $base_host."/server/image/";

$target_path = $base_dir_img . $_FILES['image']['name'] ;

if ( move_uploaded_file($_FILES['image']['tmp_name'], $target_path) ) { $dati = array(); $dati['image_url'] = $base_host_img . $_FILES['image']['name']; echo json_encode($dati); }

?>`

babbler-eu commented 3 years ago

after days of testing I managed to solve the problem, now everything works, but I will not tell anyone how I did it.

nielsvhb commented 2 years ago

How did you solve it?

babbler-eu commented 2 years ago

You know what my anger is, and that when you write a problem the authors who created all this do not calculate you at all, rather they ignore you completely, instead I think that in a software of this kind, sharing and the experience of everyone, for this I had decided not to share my result with others, but at the time I was experiencing a moment of frustration about this thing. That said, let's move on to fix the problem. When compiling your CKEditor you need to add to the ckeditor.js import SimpleUploadAdapter from '@ ckeditor / ckeditor5-upload / src / adapters / simpleuploadadapter.js'; then inside your .ts you have to add: editorConfig = { placeholder: 'Type the content here ...', simpleUpload: {uploadUrl: 'http: //localhost/upload.php'} };

this is my php

`header ('Access-Control-Allow-Origin: *');

$base_dir = $_SERVER['DOCUMENT_ROOT']; $base_host = "http://localhost/"; $base_dir_img = $base_dir."/server/image/"; $base_host_img = $base_host."/server/image/";

$ target_path = $ base_dir_img. $ _FILES ['upload'] ['name'];

if (move_uploadedfile ($ FILES ['upload'] ['tmp_name'], $ target_path)) { $ data = array (); $ data ['url'] = $ base_host_img. $ _FILES ['upload'] ['name']; echo json_encode ($ data); } `

If there are any problems, I'm here

barbarapicci commented 1 year ago

Hi Raffaele, thanks for your infos about this subject. I have a problem with the integration of Custom Upload Adapter. I can't understand how to parse $_FILES data in my php. The parser is talking with the php file, I am sure because, if I change the xhr.responseType in 'text' I can print the posted string in the console. If I change it in json type, I receive only the generic error and can't retrieve data to move_upload_files. It's frustrating, I'm working on this problem for two days... My adapter send data in json. Here the cose:

`import { environment } from 'src/environments/environment';

export class CustomUploadAdapter { loader: any; xhr: any; config:any; imagesurl = environment.APIURL+'/upload.php'; imageusername = environment.APIUSERNAME; imagepassword = environment.APIPASSWORD;

constructor( loader: any,config: any) {
    this.loader = loader;
    this.config = config;
}
upload() {
    return this.loader.file
        .then( (file: any) => new Promise( ( resolve, reject ) => {
            this._initRequest();
            this._initListeners( resolve, reject, file );
            this._sendRequest( file );
        } ) );
}
abort() {
    if ( this.xhr ) {
        this.xhr.abort();
    }
}
_initRequest() {
    const xhr = this.xhr = new XMLHttpRequest();
    //console.log('File: '+file.name);
    xhr.open( 'POST', this.imagesurl, true ); // TODO change the URL
    xhr.responseType = 'json';
xhr.setRequestHeader("Authorization", "Basic " + btoa(this.imageusername+":"+this.imagepassword));
xhr.setRequestHeader("Content-type", "application/json");
}
_initListeners( resolve: { (value: unknown): void; (arg0: { default: any; }): void; }, reject: { (reason?: any): void; (arg0: string | undefined): any; }, file: { name: any; } ) {
    const xhr = this.xhr;
    const loader = this.loader;
    const genericErrorText = `Errore di caricamento del file: ${ file.name }.`;

    xhr.addEventListener( 'error', () => reject( genericErrorText ) );
    xhr.addEventListener( 'abort', () => reject() );
    xhr.addEventListener( 'load', () => {
        const response = xhr.response;
        if ( !response || response.error ) {
            return reject( response && response.error ? response.error.message : genericErrorText );
        }
        resolve( {
            default: response.url
        } );
    } );
    if ( xhr.upload ) {
        xhr.upload.addEventListener( 'progress', (evt: { lengthComputable: any; total: any; loaded: any; }) => {
            if ( evt.lengthComputable ) {
                loader.uploadTotal = evt.total;
                loader.uploaded = evt.loaded;
            }
        } );
    }
}
_sendRequest( file: string | Blob ) {
    const data = new FormData();
    data.append( 'upload', file );
    this.xhr.send( data );
}

} `

And my upload php file:

`<?php include_once 'includes/config.inc.php';

header ('Access-Control-Allow-Origin: *'); header("Access-Control-Allow-Credentials: true"); header('Content-type: application/json');

if (!isset($_SERVER['PHP_AUTH_USER'])) { header("WWW-Authenticate: Basic realm=\"Private Area\""); header("HTTP/1.0 401 Unauthorized"); print "Sorry - you need valid credentials to be granted access!\n"; exit; } else { if (($_SERVER['PHP_AUTH_USER'] == "$apiuser") && ($_SERVER['PHP_AUTH_PW'] == "$apipassword")) {

$filename = $_FILES['upload']['name'];

if (file_exists("../images/" . $filename)) { $data = array (); $data['error'] = "Filename exists"; echo json_encode ($data); } else { $move = move_uploaded_file($_FILES['upload']['tmp_name'], "../images/" . $filename); if ($move) { print "Image moved"; $data = array (); $data['default'] = $url_immagini. $filename; echo json_encode ($data); } else { $data = array (); $data['error'] = "Error moving file"; echo json_encode ($data); }

}

} else { header("WWW-Authenticate: Basic realm=\"Private Area\""); header("HTTP/1.0 401 Unauthorized"); print "Sorry - you need valid credentials to be granted access!\n"; exit; } } ?> ` Can you help me please? Thanks in advance Barbara

barbarapicci commented 1 year ago

After days of work, I resolved the issue in this way. Hope that can help someone:

Added "allowJs": true to tsconfig.json My php file:

`$filename = $_FILES["upload"]["name"];

if ($filename) {

if (file_exists("../images/" . $filename)) { $errore = array ( 'message' => "Error: File exists!" );

         $data = [ "error" =>  $errore  ]; 
         $json = json_encode($data);
         echo $json;

        }
        else
        {
            $move = move_uploaded_file($_FILES["upload"]["tmp_name"], "../images/" . $filename);
            if ($move)
            {

$response = array("url" => $url_immagini. $filename); $dati_encode= json_encode($response); echo $dati_encode;

           }
           else
           {

$errore = array ( 'message' => "Error uploading image!" );

         $data = [ "error" =>  $errore  ]; 
         $json = json_encode($data);
         echo $json;

           }

} }`

babbler-eu commented 1 year ago

Hi Barbara, forgive me, but I only read your email today, and I'm sorry for not being of help, however I'm glad you solved it, but let me point out where the error was, in this line of the php file, $data['default'] = $url_images. $filename;should have been , $data['url'] = $url_images. $filename;which then in the end following a different path from mine, you corrected in this way $response = array("url" => $url_immagini. $filename);

babbler-eu commented 1 year ago

For a clear understanding of what I wrote above, which may also help someone in the future, I would like to point out why I used $data ['url'] = $base_host_img. $ _FILES ['upload'] ['name'];. If you look closely inside _initRequest() there is this code fragment that validates the response,

resolve( {
             default: response.url
         } );

In fact if you try to change ['url'], in ['default'], like our Barbara, it doesn't work. I hope I have been helpful.