Skip to content

Instantly share code, notes, and snippets.

@fowkswe
Last active October 27, 2024 17:49
Show Gist options
  • Save fowkswe/3db02f1d355cab1dc300 to your computer and use it in GitHub Desktop.
Save fowkswe/3db02f1d355cab1dc300 to your computer and use it in GitHub Desktop.
Replacement for sendy's upload.php that sends files to S3 rather than the server.
<?php
//
// this replaces includes/create/upload.php - besure to save your old upload.php!
// you must put the S3.php file in includes/helpers/S3.php
// you can get it here:
// https://github.com/tpyo/amazon-s3-php-class
//
// This is an improvement on this gist:
// https://gist.github.com/Wysie/03934b6a79a715772abd
//
// Ensure your AWS user has propper credentials to upload to s3
//
// Be sure to set your bucket name and region url below.
//
include('../functions.php');
include('../login/auth.php');
require_once('../helpers/S3.php');
//Init
$file = $_FILES['upload']['tmp_name'];
$fileName = $_FILES['upload']['name'];
$extension_explode = explode('.', $fileName);
$extension = $extension_explode[count($extension_explode)-1];
$time = time();
$allowed = array("jpeg", "jpg", "gif", "png");
if(in_array($extension, $allowed)) {
$awsAccessKey = get_app_info('s3_key');
$awsSecretKey = get_app_info('s3_secret');
$bucketName = 'YOURBUCKET'; //Change accordingly
$endpoint = 's3-us-west-2.amazonaws.com'; //Change accordingly
$s3 = new S3($awsAccessKey, $awsSecretKey, false, $endpoint);
$s3Filename = $time.baseName($fileName);
if ($s3 -> putObject($s3->inputFile($file), $bucketName, $s3Filename, S3::ACL_PUBLIC_READ)) {
$array = array(
'filelink' => 'http://'.$endpoint.'/'.$bucketName.'/'.$s3Filename
);
// echo stripslashes(json_encode($array));
// Required: anonymous function reference number as explained above.
$funcNum = $_GET['CKEditorFuncNum'] ;
// Optional: instance name (might be used to load a specific configuration file or anything else).
$CKEditor = $_GET['CKEditor'] ;
// Optional: might be used to provide localized messages.
$langCode = $_GET['langCode'] ;
// Check the $_FILES array and save the file. Assign the correct path to a variable ($url).
$url = APP_PATH.'/uploads/'.$time.'.'.$extension;
$url = 'http://'.$endpoint.'/'.$bucketName.'/'.$s3Filename;
// Usually you will only assign something here if the file could not be uploaded.
$message = '';
echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$url', '$message');</script>";
}
else {
die('there was a problem');
}
}
else {
die('File not allowed');
}
?>
@murrinmedia
Copy link

I can't seem to get this working.
It appears to be set up correctly :/

@eldyvoon
Copy link

is this working? I've put in correct bucket name and endpoint but it doesn't work for me :/ What else I missed out?

@philamery
Copy link

hi folks,
just asking, does this stuff work?
if possible I want to avoid wasting time with it

@burhanattime
Copy link

Updated the above with lots of error handling as I struggled to get it working. For the below script to work, you'll need to make sure that your php.ini file and server is setup to support it. I had to do the following:

  • Set upload_tmp_dir = /tmp
  • While I was in there, I set upload_max_filesize = 10M and post_max_size = 10M as well
  • Added policy to the IAM user:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        }
    ]
}
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

include('../functions.php');
include('../login/auth.php');
require_once('../helpers/S3.php');

if (!isset($_FILES['upload'])) {
    die('No file uploaded');
}

// Init
$file = $_FILES['upload']['tmp_name'];
$fileName = $_FILES['upload']['name'];
$uploadError = $_FILES['upload']['error'];

if ($uploadError !== UPLOAD_ERR_OK) {
    switch ($uploadError) {
        case UPLOAD_ERR_INI_SIZE:
            $message = "The uploaded file exceeds the upload_max_filesize directive in php.ini.";
            break;
        case UPLOAD_ERR_FORM_SIZE:
            $message = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.";
            break;
        case UPLOAD_ERR_PARTIAL:
            $message = "The uploaded file was only partially uploaded.";
            break;
        case UPLOAD_ERR_NO_FILE:
            $message = "No file was uploaded.";
            break;
        case UPLOAD_ERR_NO_TMP_DIR:
            $message = "Missing a temporary folder.";
            break;
        case UPLOAD_ERR_CANT_WRITE:
            $message = "Failed to write file to disk.";
            break;
        case UPLOAD_ERR_EXTENSION:
            $message = "File upload stopped by extension.";
            break;
        default:
            $message = "Unknown upload error.";
            break;
    }
    die($message);
}

$extension_explode = explode('.', $fileName);
$extension = end($extension_explode);
$time = time();
$allowed = array("jpeg", "jpg", "gif", "png");

if (!in_array($extension, $allowed)) {
    die('File not allowed');
}

$awsAccessKey = get_app_info('s3_key');
$awsSecretKey = get_app_info('s3_secret');
if (!$awsAccessKey || !$awsSecretKey) {
    die('AWS credentials are missing');
}

$bucketName = 'YOUR_BUCKET_NAME'; //change to your bucket name
$endpoint = 's3.us-east-1.amazonaws.com'; //change as appropriate

try {
    $s3 = new S3($awsAccessKey, $awsSecretKey, false, $endpoint);
} catch (Exception $e) {
    die('Failed to initialize S3: ' . $e->getMessage());
}

$s3Filename = 'images/' . $time . basename($fileName); //added path to images folder on S3 bucket

// Additional debugging
echo "<script type='text/javascript'>console.log('Attempting to upload to S3: $s3Filename');</script>";

try {
    if (!file_exists($file)) {
        throw new Exception('Temporary file does not exist');
    }
    if (filesize($file) === 0) {
        throw new Exception('Temporary file is empty');
    }

    // Logging file details for debugging
    echo "<script type='text/javascript'>console.log('File exists: " . file_exists($file) . "');</script>";
    echo "<script type='text/javascript'>console.log('File size: " . filesize($file) . "');</script>";

    $inputFile = $s3->inputFile($file);
    if (!$inputFile) {
        throw new Exception('Unable to create input file for S3 upload');
    }

    // Logging input file details
    echo "<script type='text/javascript'>console.log('Input file: " . json_encode($inputFile) . "');</script>";

    $result = $s3->putObject($inputFile, $bucketName, $s3Filename);
    if ($result) {
        $fileUrl = 'https://' . $bucketName . '.' . $endpoint . '/' . $s3Filename;

        // Additional debugging
        echo "<script type='text/javascript'>console.log('File uploaded successfully. URL: $fileUrl');</script>";

        $funcNum = $_GET['CKEditorFuncNum'];
        $CKEditor = $_GET['CKEditor'];
        $langCode = $_GET['langCode'];
        $message = '';

        echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$fileUrl', '$message');</script>";
    } else {
        throw new Exception('S3 upload failed');
    }
} catch (Exception $e) {
    $errorMessage = $e->getMessage();
    error_log('Failed to upload to S3: ' . $errorMessage);
    echo "<script type='text/javascript'>console.log('Error: $errorMessage');</script>";
    die('Failed to upload to S3: ' . $errorMessage);
}
?>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment