MyBB Community Forums

Full Version: Self Hosted Images - which do quote!
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I don't know if anyone wants this (except me) but to be able to self host a forums images, I consider a good idea and that those images are quotable greatly helps the flow of a thread.

I was talking about how to make this work in another thread and now that it seems that it does work .... I thought that it may need it's own thread so that anyone who wants to do it can find this information.

It is one PHP file and some added code to each of the editors (there are 3 editors, New Reply, New Thread and Edit Post).
I also made 2 new directories .... one to contain the uploaded images and the other just to contain the PHP file.

The 'upload' button I placed under the 'Smilies' .... it looks like this:

[attachment=46725]

but you can style it anyway you wish (the style of it I left under the form for ease of change but it could be moved).

Clicking that button opens your files (as normal) and once you select an image it uploads the file to your server/webspace and returns the new URL of your image (the file name gets changed to a unique name to stop any conflicts) which it places in to the editor textarea:

[attachment=46726]

The image does not show at first in the wysiwyg view, but it is linked and ready.
You don't need to do this but a preview or click the source mode then back to wysiwyg will show that it is there:

[attachment=46727]

The php file I put in a directory called "aaaAPI" (but it can be anything you decide, just be sure to link it correctly in the JS Function) and the directory I made for the images I called "serveImage" .... just saying so you know them in the code.

The php code is:

<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods, Authorization");

$fileName  =  $_FILES['imageFile']['name'];
$tempPath  =  $_FILES['imageFile']['tmp_name'];
$fileSize  =  $_FILES['imageFile']['size'];
$fileError =  $_FILES['imageFile']['error'];

$requestMethod = $_SERVER['REQUEST_METHOD'];

if ($requestMethod == 'POST') {

    if (!empty($fileName)) {

        $upload_path = '../serveImage/';
        $server_url  =  "https://example.com/serveImage";

        $fileExt = explode('.', $fileName);
        $fileActExt = strtolower(end($fileExt));
        $fileName = "WC-" . uniqid() . "." . $fileActExt;

        $valid_extensions = array('jpeg', 'jpg', 'png', 'gif');

        if (in_array($fileActExt, $valid_extensions)) {

            if (!file_exists($upload_path . $fileName)) {

                if ($fileSize < 2000000 && $fileError == 0) {

                    if (move_uploaded_file($tempPath, $upload_path . $fileName)) {
                        $response = [
                            "url" => $server_url . "/" . $fileName
                        ];
                    } else {
                        $response = [
                            'status' => false,
                            'message' => "File couldn't be uploaded",
                        ];
                    }
                } else {
                    $response = [
                        'status' => false,
                        'message' => "Your file is too large, please upload 2 MB size",
                    ];
                }
            } else {
                $response = [
                    'status' => false,
                    'message' => "File already exists check upload folder",
                ];
            }
        } else {
            $response = [
                'status' => false,
                'message' => "Only image files are allowed",
            ];
        }
    } else {
        $response = [
            'status' => false,
            'message' => "Please select a file",
        ];
    }
} else {
    $response = [
        'status' => false,
        'message' => $requestMethod . ' Method not allowed',
    ];
}

echo json_encode($response);
?>


The code added to each editor.
I put this directly after the {$smilieinserter} .... so the line which looks like this:

<td class="trow2" valign="top"><strong>{$lang->your_message}</strong><br />{$smilieinserter}</td>

I returned down the </ td> and placed the code before it (so including the above line and the final </ td> it looks like this)

<td class="trow2" valign="top"><strong>{$lang->your_message}</strong><br />{$smilieinserter}
	<p>
<form id="uploadForm" enctype="multipart/form-data">
    <label for="fileInput" class="server-file-upload">
        Upload Image
    </label>
    <input type="file" id="fileInput" name="fileInput" accept="image/*" onchange="serverUpload()">
</form>
</p>
<style>
    .server-file-upload {
        background-color: #2980b9;
        border-radius: 12px;
        max-width: 50%; 
        margin-left: 35%; 
        color: #fff; 
        text-align: center; 
        border: 2px solid #000000; 
        font-weight: bold;
        margin-top: 20px;
    }

    .server-file-upload:hover {
        background-color: #04AA6D;
        box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
    }


    #fileInput {
        display: none;
    }
</style>


	<script>
      function serverUpload() {
    let fileInput = document.getElementById('fileInput');
    let file = fileInput.files[0];

    if (!file) {
        alert('Please select an image.');
        return;
    }

    let formData = new FormData();
    formData.append('imageFile', file);

    let phpUrl = 'https://example.com/aaaAPI/actionFromjs.php';

    fetch(phpUrl, {
        method: 'POST',
        body: formData
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('Failed');
        }
        return response.json();
    })
    .then(data => {
        let code = "[img]" + data.url + "[/img]";
        if (window.MyBBEditor) {
            window.MyBBEditor.insertText(code);
        } else {
            throw 'Upload error';
        }
    })
    .catch(error => {
        console.error('Error:', error);
    });
}

    </script>
	
	</td>

All the images show in any quote of the post.
I am sure that it can be made better but it does what I need it for Big Grin 

Any thoughts on mistakes I may have made or improvements would be gladly accepted.

forgot to say ....

set the correct permissions on the new directories (if you use new ones).

and this was done on a base MyBB version 1.8.37 (no added theme) and php 8.2.16
(2024-03-02, 01:51 PM)lost puppy Wrote: [ -> ]Any thoughts on mistakes I may have made or improvements would be gladly accepted.

The main two improvements I'd suggest are:

  1. To validate in the PHP code that the file is being uploaded by a logged in member of your board, otherwise any old anonymous troublemaker could upload images and waste your bandwidth/storage.
  2. To split the upload directory into multiple subdirectories, as MyBB core does for its uploads directory, because random accesses to files slow down for most filesystem types as the number of files in the directory grows.
Properly set Access-Control-Allow-Origin to your domain to avoid unauthorized usage.
https://developer.mozilla.org/en-US/docs...low-Origin
@Laird and @effone

Thank you both for the ideas and I shall try and implement them Smile
I have changed this a tad!

Mods .... this isn't really "Support" so if you wish to move it, please do so? (have you a forum section which is for "old blokes chatting to themselves"?)

I have made it so that only one template is added to (simlieinsert) rather than the 3 editor templates and have added the option to resize the image on upload.
The resize options are 90% down to 10%.

[attachment=46804]

If the resize option is not taken then the original image is uploaded and placed into the editor textarea.

I can't yet get it to create a new directory each month for the image file uploads but I will get it working Smile

Next I need to get the added PHP file to know the domain URL automatically?

So in effect there is now only one file which is new, one change to one template and one directory needing creation for it to work!
I will make this a plugin .... eventually (still doing work so time is limited and I currently do not know how to make a plugin Toungue )

edit to add .... and one small css file to be added!