I have created a custom plugin to allow users to upload their videos on the website, which are then stored on the Bunny.net server. After testing, I noticed that if the video is larger than 300MB, I always receive the error 413 (Request Entity Too Large).
This my jQuery handle when upload file
$form.on('submit', async function (e) {
e.preventDefault();
const $status = $form.find('.upload-status');
const $progressContainer = $form.find('.progress-container');
const $progress = $form.find('.upload-progress');
const $percentage = $form.find('.progress-percentage');
const $submitButton = $form.find('button[type="submit"]');
const $fileInput = $(SELECTORS.fileInput);
if ($fileInput[0].files.length === 0) {
showStatus($status, ub_ajax.i18n.select_file || 'Please select a video file to upload.', true);
return;
}
const formData = new FormData();
formData.append('action', 'upload_video');
formData.append('nonce', ub_ajax.nonce);
formData.append('video_file', $fileInput[0].files[0]);
formData.append('collection_id', $fileInput.data('collection-id'));
$submitButton.prop('disabled', true);
$progressContainer.show();
showStatus($status, ub_ajax.i18n.upload_progress || 'Upload in progress...');
try {
const response = await $.ajax({
url: ub_ajax.ajax_url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
xhr: function () {
const xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', (evt) => {
if (evt.lengthComputable) {
const percentComplete = (evt.loaded / evt.total) * 100;
$progress.val(percentComplete < 99 ? percentComplete : 99);
$percentage.text(`${Math.round(percentComplete < 99 ? percentComplete : 99)}%`);
}
});
return xhr;
}
});
if (response.success) {
$progress.val(100);
$percentage.text('100%');
showStatus($status, response.data.message);
setTimeout(() => location.reload(), 1500);
} else {
throw new Error(response.data.message || ub_ajax.i18n.upload_failed || 'Upload failed. Please try again.');
}
} catch (error) {
const errorMessage = error.responseJSON?.data?.message || error.message || ub_ajax.i18n.generic_error || 'An error occurred. Please try again.';
showStatus($status, errorMessage, true);
$submitButton.prop('disabled', false);
} finally {
$progressContainer.hide();
$submitButton.prop('disabled', false);
}
});
This is handle api upload video
add_action('wp_ajax_upload_video', 'ub_upload_video');
add_action('wp_ajax_nopriv_upload_video', 'ub_upload_video');
define('ALLOWED_MIME_TYPES', ['video/mp4', 'video/mkv', 'video/avi']);
@ini_set('upload_max_filesize', '0');
@ini_set('post_max_size', '0');
@ini_set('memory_limit', '-1');
@set_time_limit(0);
function ub_upload_video()
{
try {
verify_upload_request();
$file = validate_video_file();
$credentials = get_bunny_credentials();
$collection_id = isset($_POST['collection_id']) ? sanitize_text_field($_POST['collection_id']) : '';
$video_id = create_bunny_video($credentials, $collection_id, $file);
upload_video_to_bunny($credentials, $video_id, $file);
wp_send_json_success([
'message' => __('Video uploaded successfully!', 'upload-bunny'),
'video_id' => $video_id
]);
} catch (Exception $e) {
wp_send_json_error([
'message' => $e->getMessage(),
'code' => $e->getCode()
]);
}
}
function verify_upload_request()
{
check_ajax_referer('ub_ajax_nonce', 'nonce');
if (!current_user_can('stm_lms_instructor')) {
throw new Exception('You do not have permission to perform this action.', 403);
}
}
function validate_video_file()
{
if (empty($_FILES['video_file']) || $_FILES['video_file']['error'] !== UPLOAD_ERR_OK) {
throw new Exception('No file uploaded or there was an error uploading the file.', 400);
}
$file = $_FILES['video_file'];
update_option('file', $file);
return $file;
}
function get_bunny_credentials()
{
$user_id = get_current_user_id();
$library_id = get_option('_bunny_library_id_' . $user_id);
$library_api_key = get_option('_bunny_library_api_key_' . $user_id);
if (!$library_id || !$library_api_key) {
throw new Exception('Missing Bunny.net library credentials.', 400);
}
return [
'library_id' => $library_id,
'api_key' => $library_api_key
];
}
function create_bunny_video($credentials, $collection_id, $file)
{
$api_url = UploadBunny::get_base_url() . '/library/' . $credentials['library_id'] . '/videos';
$data = [
'title' => sanitize_file_name($file['name']),
'collectionId' => $collection_id,
];
$response = wp_remote_post($api_url, array(
'headers' => array(
'Content-Type' => 'application/json',
'AccessKey' => $credentials['api_key'],
),
'body' => json_encode($data),
'timeout' => 30,
));
if (is_wp_error($response)) {
throw new Exception($response->get_error_message(), 500);
}
$response_code = wp_remote_retrieve_response_code($response);
$response_body = json_decode(wp_remote_retrieve_body($response), true);
if ($response_code !== 200 && $response_code !== 201) {
$error_message = isset($response_body['message']) ? $response_body['message'] : 'Failed to create video.';
throw new Exception($error_message, $response_code);
}
if (!isset($response_body['guid'])) {
throw new Exception('Invalid response from Bunny.net API.', 500);
}
return $response_body['guid'];
}
function upload_video_to_bunny($credentials, $video_id, $file)
{
$api_url = UploadBunny::get_base_url() . '/library/' . $credentials['library_id'] . '/videos/' . $video_id;
$file_content = file_get_contents($file['tmp_name']);
$response = wp_remote_request($api_url, array(
'method' => 'PUT',
'headers' => array(
'Accept' => 'application/json',
'AccessKey' => $credentials['api_key'],
'Content-Type' => 'application/octet-stream',
),
'body' => $file_content,
'timeout' => 120,
));
if (is_wp_error($response)) {
throw new Exception($response->get_error_message(), 500);
}
$response_code = wp_remote_retrieve_response_code($response);
$response_body = wp_remote_retrieve_body($response);
error_log("Response Code: " . $response_code);
error_log("Response Body: " . print_r($response_body, true));
$response_body = json_decode($response_body, true);
if ($response_code !== 200 && $response_code !== 201) {
$error_message = isset($response_body['message']) ? $response_body['message'] : 'Failed to upload video.';
throw new Exception($error_message, $response_code);
}
return $response_body;
}
Does anyone have a solution for this problem? I want users to be able to upload any file without worrying about file size, as sometimes videos can be more than 20GB.