Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Upload Image to S3 using Advance Editor not working

Hi Team,

I managed to upload to S3 bucket using the normal 'Add Images' button by hooks to 'userController_pluginname_create'. However it's not working on the Advance Editor, when I click the Editor 'Attach Image' and select the file, it's showing 'The file failed to upload'. The error logs doesn't show anything related. I tried hooks to 'GDN_Upload_saveAs_handler' still shows same 'The file failed to upload' error.

On the chrome dev console it throws 'Uncaught Error: Invalid clickable option provided. Please provide a CSS selector, a plain HTML element or a list of those.' which is related to dropzone.js files. What is our hooks to Advance Editor Image upload? Or is it on the Advance Editor Plugin?

Need some insights, TIA.

BTW, Advance Editor post format settings is Wyssiwyg.

Comments

  • The advanced editor makes use of Gdn_Upload, too. Therefore gdn_upload_saveAs_handler is fired and must be used to upload to S3.

    The error that you are quoting complains about the "clickable" option. You should check where that is used in your code. I do not find it in the advanced editors source. Could it be that you have made (wrong) use of it?


    By the way: if you have a working plugin to upload to S3, it would be great if you could publish it. I bet many people would like to see something like that. :wink:

  • martin28martin28 New
    edited August 2018

    @R_J I'll consult my Boss first if I can publish the plugin, it's company owned.

    BTW, I managed to upload to s3 using the Advance Editor, my little challenge is the images uploaded from editor still showing the local path (uploads/editor/...). I guess I have to put condition on the theme.

  • I'm not sure I understand that little problem, but make sure that you are not fooled by "old" information stored in the Media table.
    If that problem also comes up with newly uploaded files, you should inspect the editors methogetBaseUploadDestinationDir() which I would assume will always return 'uploads/editor' the way it is used in the editor.

  • @R_J how do I hook the image source path, currently all images uploaded using the advance editor are pulling up the image from /uploads/editor folder, while all the images uploaded using the add images button are pulling up images from our s3 bucket. I can see that images uploaded using advance editor are also on our s3 bucket, so i want to change the image src of the images uploaded using the advance editor from 'uploads/editor/...' to our s3 bucket path.

    I'm looking at 'discussionController_Render_Before' hooks, but how do I hook the image src?

    TIA

  • Is the info in the Media table correct or does it already show the wrong /uploads/editor path?

  • In the media table it show's correct path. It show's editor/... if uploaded using editor, it shows comment/... or discussion/... if uploaded using Add images button.

  • I would try editing class.editor.plugin.php, method "getBaseUploadDestinationDir" to see if that is the problem. If it is the problem, next step would be to think about how to work around that issue...

  • martin28martin28 New
    edited August 2018

    I tried changing the getBaseUploadDestinationDir basepath it did not work. I'm not sure it's problem with destination folder since it's saving on uploads/editor folder & on our s3 bucket. The only challenge is when displaying those images, if uploaded from editor img src is the "uploads/editor + img path" while if uploaded using the add image button, it's img src is our "s3 bucket + img path".

    Is there like a hook before discussion render to update all img src?

  • Not really a hook... Such functions are in /library/core/functions.render.php and you are able to override them:

    if (!function_exists('img')) {
        /**
         * Returns an img tag.
         *
         * @param string $image
         * @param string $attributes
         * @param bool|false $withDomain
         * @return string
         */
        function img($image, $attributes = '', $withDomain = false) {
            if ($attributes != '') {
                $attributes = attribute($attributes);
            }
    
            if (!isUrl($image)) {
                $image = smartAsset($image, $withDomain);
            }
    
            return '<img src="'.htmlspecialchars($image, ENT_QUOTES).'"'.$attributes.' />';
        }
    }
    

    If you add a "function img()" below your plugin, you would be able to change that function.

    But I'm not sure that this is the best approach. You should find the place where the "uploads/editor" is build and try to correct it there.

  • Which view is displaying the wrong path? Or is it shown wrong inside a discussion/comment?

  • Discussion view & discussion with comment view.

  • This one is your problem: Gdn_Upload::url();. Here is the proof:

        public function vanillaController_uploadParseTest_create($sender) {
            $path = 'S3/editor/123.jpg';
            decho(Gdn_Upload::url($path));
        }
    

    But this function calls Gdn_Upload::urls() which has the following description:

        /**
         * Returns the url prefix for a given type.
         *
         * If there is a plugin that wants to store uploads at a different location or in a different way then they register
         * themselves by subscribing to the Gdn_Upload_GetUrls_Handler event. After that they will be available here.
         *
         * @param string $type The type of upload to get the prefix for.
         * @return string The url prefix.
         */
    

    Sounds promising.

    If you ask me, your plugin should add a "namespace" to newly saved images because otherwise it would never be possible to differentiate between images still and only available locally and images only available on S3.
    it is needed for this solution, too.

    So you would have to save your file as "S3:editor/123.jpg" and then you need to "install" a handler for your own "S3-protocol".

        public function gdn_upload_getUrls_handler($sender, $args) {
            $args['Urls']['S3'] = 'amazon/S3';
        }
    

    After that, decho(Gdn_Upload::url('S3:editor/123.jpg')); will show amazon/S3/editor/123.jpg which I guess is what you need.

  • How do I use the gdn_upload_getUrls_handler $args 'S3' to update the image src?

  • x00x00 MVP
    edited August 2018

    Personally I think you are approaching this the wrong way, either symlink the uploads folder to the mounted and linked storage or change the uploads directory by predefining the constant in boostrap.before.php (due to a bug this must be a relative path), which will prevent it from being overwritten.

    grep is your friend.

  • The answer has something to do with how a url for a S3 bucket has to look and I do not know that...

    The idea is, that your plugin has to mark an entry in the Media table somehow so that you can distinguish between uploads which have happened without your plugin (to local disc) and with your plugin (to amazon).
    That is a requirement that your plugin needs to fulfill if it is set up correct and clean.

    When saving the file, you have to make sure that the path in the Media table reads "S3:editor/whatever" and that is the way to distinguish normal uploads form uploads made with the plugin.

    The getUrls handler fires when the Upload::url() method is used. It allows you to replace "S3:" with whatever is needed. Therefore I think it is needed that you save the files in a similar structure in the bucket. So if the Path field shows "S3:editor/123/abc.png", you have to be able to access the file by "whateverurlisneededhere.com/maybe/some/other/path/here/editor/123/abc.png"

    If you need additional GET paramaters, e.g. "example.com/some/bucket/abc.png?paramX=123", I think you are lost :-(


    But using a symlink is way more elegant, indeed! Having an S3 upload plugin would only make sense for people who do not own their server but only have a hosting package on a shared server

  • Media table path captures the folder name + image name (folder names are either discussion, comment, editor ...). There's a column in Media table "StorageMethod" (it labels 's3' if using the add image button & labels 'local' if using the wysiwyg), I may have to look into that since the forum has been running for years now, saving it on different path might break old images.

    Apology for the hassle, I'll update this post for any progress.

  • Fixed it through js, intercepted the add image on editor with s3 functions.

Sign In or Register to comment.