See SendAjax # Example 1 This is a simple example using Javascript and {PHP} ## AJAX Core The core that makes it work is ```js const xhttp = new XMLHttpRequest() xhttp.open("POST", ".upload", true) xhttp.onload = function (event) { const responseText = this.responseText console.log({responseText}) const response = JSON.parse(responseText) console.log({response}) const status = xhttp.status if (status == 200) { const { result, error, files } = response if (result === "error") { display_error(error) } else { on_successful_upload(files, result) } } else { // this will happen if you don't have write permission at time of upload (a 403) display_error(`status ${status}: ${responseText}`) } } // if sending a form xhttp.send(form_data) // if sending json xhttp.setRequestHeader("Content-Type", "application/json") xhttp.send(JSON.stringify(data)) ``` and for receiving a form ```php $data = $_POST; ``` and for receiving {JSON} ```php $data = json_decode(file_get_contents('php://input'), true); ``` and for receiving files ```php foreach ($_FILES['file']['name'] as $key=>$val) { $filename = $_FILES['file']['name'][$key]; $filename = preg_replace('/[^a-zA-Z0-9_\-@\. ]+/',"_",$filename); $tmp_name = $_FILES['file']['tmp_name'][$key]; $target = trim($subdir,"/")."/".$filename; if( ! $wiki->valid_file_path($target) ) { array_push($files_results,make_error($filename,"Filename '$filename' is not acceptable")); $failures++; } else { // filename ok try { $storage->store_uploaded($tmp_name,$target); array_push($files_results,array("filename"=>$filename,"result"=>"success","error"=>null)); $successes++; } catch( Exception $e ) { array_push($files_results,make_error($filename,"Failed to move '$filename' -- ".$e->getMessage())); $failures++; } } } ``` everything else below is a wrapper ## Javascript ```js // // Code adapted from https://artisansweb.net/drag-drop-file-upload-using-javascript-php/ // (function() { window.addEventListener("load",_ => { let fileobj function upload_file(e) { console.log({msg:"upload file"}) e.preventDefault() ajax_file_upload(e.dataTransfer.files) } function filename_is_image(filename) { return filename.match(/aw/\.(jpg|jpeg|jfif|png|webp|gif|svg)$/) } function on_successful_upload(files, result) { console.log({msg:"upload",files,result}) const successful_files = files.filter(x => x.result === "success" ) let msg if( result === "partial" ) { msg = `Partial success: ${successful_files.length}/${files.length} uploaded` } else { msg = `Success: ${successful_files.length}/${files.length} uploaded` } const msgarr = [] for(let i=0; i${filename} — ${error}`) } else { const img = filename_is_image(filename) ? ` ` : "" msgarr.push(`${filename}${img}`) } } msg += "
\n" + msgarr.join("
\n") // do something to tell the user the result display_notification(msg,true) // supply this function yourself } // ACTUAL UPLOADER function ajax_file_upload(files_obj) { console.log(files_obj) if (files_obj != undefined) { var form_data = new FormData(); for (let i = 0; i < files_obj.length; i++) { console.log(files_obj) form_data.append('file[]', files_obj[i]) } form_data.append('location',window.location.href) console.log(`uploading`, files_obj); display_notification(`Uploading ${Array.from(files_obj).map(x => x.name).join(", ")}`) var xhttp = new XMLHttpRequest(); xhttp.open("POST", ".upload", true); xhttp.onload = function (event) { const responseText = this.responseText console.log({responseText}) const response = JSON.parse(responseText) console.log({response}) const status = xhttp.status if (status == 200) { const { result, error, files } = response if (result === "error") { display_error(error) } else { on_successful_upload(files, result) } } else { // this will happen if you don't have write permission at time of upload (a 403) display_error(`status ${status}: ${responseText}`) } } xhttp.send(form_data); } } }) })() ``` ## PHP ```php php # # Code adapted from https://artisansweb.net/drag-drop-file-upload-using-javascript-php/ # function store_uploaded_file($tmp_name,$filename) { return move_uploaded_file($tmp_name,$filename); } function return_error(string $msg, int $response_code = 400) : void { http_response_code($response_code); file_put_contents("error.txt",$msg); echo json_encode(["error" => $msg]); die; } function return_json($obj) : void { echo json_encode($obj); die; } function make_error($filename,$error) { return array("filename" => $filename, "result"=> "error", "error"=>$error); } umask(0); $status = "success"; $error = null; $files_results = array(); $successes = 0; $failures = 0; if( ! isset($_POST) || ! array_key_exists('location',$_POST) ) { return_error("Invalid upload data -- no location"); } $location = parse_url($_POST['location']); $path = urldecode($location['path']); $subdir = dirname($path); foreach ($_FILES['file']['name'] as $key=>$val) { $filename = $_FILES['file']['name'][$key]; $filename = preg_replace('/[^a-zA-Z0-9_\-@\. ]+/',"_",$filename); $tmp_name = $_FILES['file']['tmp_name'][$key]; $target = trim($subdir,"/")."/".$filename; if( ! $wiki->valid_file_path($target) ) { array_push($files_results,make_error($filename,"Filename '$filename' is not acceptable")); $failures++; } else { // filename ok try { $storage->store_uploaded($tmp_name,$target); array_push($files_results,array("filename"=>$filename,"result"=>"success","error"=>null)); $successes++; } catch( Exception $e ) { array_push($files_results,make_error($filename,"Failed to move '$filename' -- ".$e->getMessage())); $failures++; } } } $return_obj = array( "error"=> ($successes == 0 ? "No files uploaded" : null), "result"=> ($successes > 0 && $failures == 0 ? "success" : ($successes > 0 && $failures > 0 ? "partial" : "error" )), "files"=> $files_results ); $json = json_encode($return_obj); echo $json; exit(); ```