Image upload via AJAX/html/php

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
Hey allen, voor school heb ik een projectje, en een subdeel daarvan is om een imagefile up te loaden naar een lokale server.
Ik wil nadat er geklikt wordt op "Upload mijn image" een message zien verschijnen of de image succesvol upgeload is of niet, zonder dat de page moet refreshen. Daarvoor wil ik dus AJAX gaan gebruiken.

Helaas loopt er een heleboel mis, gaande van een "fakepath" tot "undefined indexen".

Mijn structuur bestaat uit 3 onderdelen:

De html pagina waarin je de foto laadt en dan op uploaden klikt: uploadform.html.
Hierin
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="main.css">
        <title>Upload a picture</title>
        
        <script>
            function ajax_post(){
                // Create our XMLHttpRequest object
                var hr = new XMLHttpRequest();
                // Create some variables we need to send to our PHP file
                var url = "../Controller/controller.php";
                var f = document.getElementById("fileToUpload").value;
                var vars = "f="+f;
                
                hr.open("POST", url, true);
                // Set content type header information for sending url encoded variables in the request
                hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                // Access the onreadystatechange event for the XMLHttpRequest object
                hr.onreadystatechange = function() {
                    if(hr.readyState == 4 && hr.status == 200) {
                        var return_data = hr.responseText;
                        document.getElementById("status").innerHTML = return_data;
                    }
                }
                // Send the data to PHP now... and wait for response to update the status div
                hr.send(vars); // Actually execute the request
                document.getElementById("status").innerHTML = "processing...";
            }
        </script>
    </head>
    
    <body>
            
            <!-- maximum upload size is 5Mb -->
            
            <input type="hidden" name="MAX_FILE_SIZE" value="5000000" />
    
            <p>
                Select a picture to upload:
                <input id="fileToUpload" type="file" name="fileToUpload" >
            </p>
            
            <p>
                <input type="submit" value="Upload my image!" name="uploadImagetest" onclick="javascript:ajax_post();">
                <br/>
            </p>
            
            <p id="status"></p>
         
      
    </body>
</html>


Dan heb ik mijn controller (deze is nodig voor het volledige project, en de bedoeling is dat deze alle info van de front-end binnenkrijgt en dan naar de juiste php-files doorstuurt): controller.php:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
include("../Filemanager/filemanager.php");

//If the "uploadImage" button is pressed, all the data gets sent here and the right functions are called to upload the picture in local webserver(image)

    //make sure all info is given
    if( ($_POST["f"] != null) ){
        
        $path = uploadImage($_POST["f"]);
        //Hier staan dan nog functies uit andere php die een upload naar een mySQL-database doen.
        echo "File uploaded correctly";
    } else{
        echo "Please make sure all the info is given.";
    }


En dan heb ik nog mijn filemanager.php file die voor het effectieve uploaden van de image naar mijn lokale server zorgt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
$folder = "../uploads/";

function uploadImage($picture){
    global $folder;
    $picture = str_replace( "C:\\fakepath\\", '', $picture); //AJAX-request makes a fakepath but we don't want that
    $upload_image = $folder . basename($_FILES[$picture]["name"]);
    
    //whitespace removal form the filename
    $upload_image = preg_replace('/\s+/', '', $upload_image);
    
    //filetype opvragen
    $imageFileType = strtolower(pathinfo($upload_image,PATHINFO_EXTENSION));
    
    //De toegelaten extensies in een array
    $extensions_arr = array("jpg","jpeg","png","gif");
    
    //check if uploaded file is an image of the correct form
    if (in_array($imageFileType, $extensions_arr) ){
    
        
            if (move_uploaded_file($_FILES[$picture]["tmp_name"], $upload_image)) {
                echo "The file ". basename( $_FILES[$picture]["name"]). " has been uploaded.";
                return $upload_image;
            } else {
                //incorrect process of uploading gives error
                echo "Sorry, there was an error uploading your file.";
            }
        } else {
            //incorrect format gives exception
            echo "The selected file is not of the right extension. We only accept jpg, jpeg, png or gif files.";
    }
    return null;
    } 
?>


Nu wat is mijn probleem: ik merkte reeds op dat door via AJAX te gaan werken, mijn path van de file veranderen naar C:\fakepath\imagename.png, maar dat wou ik dus niet. Ik heb dit opgevangen in mijn functie "uploadImage" in "filemanager.php".

Ik krijg volgende error: Notice: Undefined index: C:\fakepath\apple.png in C:\xampp\htdocs\Ugesco\Controller\controller.php on line 87 als ik gebruik maak van de $FILES[]-methode. Met andere woorden, ik denk dat mijn AJAX-script en functie "ajax_post()" in "uploadform.html" mijn file (de image) niet correct doorgeeft naar de php-files.

Voor ik AJAX gebruikte, werkte ik gewoon met een form, en deze POST dit door naar de php's. Wel moest de pagina telkens gerefreshed worden maar het werkte wel om die $FILES[]-methodes te gebruiken. Sinds ik die AJAX gebruik, werkt dit niet meer.

Ik heb reeds getest met gewone info, zoals een textvak met normale text in. Dan wordt alles mooi doorgegeven.

Ik blijf hier maar op zoeken maar vind geen oplossing, heeft iemand raad?

[ Voor 28% gewijzigd door BramCoding op 10-05-2018 22:10 ]

Beste antwoord (via BramCoding op 12-05-2018 20:54)


  • DJMaze
  • Registratie: Juni 2002
  • Niet online
BramVanha schreef op vrijdag 11 mei 2018 @ 15:06:
Ik vind zoveel tutorials online over mijn probleem, maar geen enkele werkt of toont alles. Dus ik probeer nu allemaal dingen aan elkaar te hangen maar zoals verwacht schuift dit voor geen millimeter |:(
Dat komt omdat ze erg uitgebreid zijn.

Dit is de meest minimale basis:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php
if ('POST' === $_SERVER['REQUEST_METHOD']) {
    if (!isset($_FILES['afbeelding'])) {
        header($_SERVER['SERVER_PROTOCOL'].' 412 Precondition Failed', true, 412);
        exit('Er ging iets mis met het formulier');
    }
    if (!empty($_FILES['afbeelding']['error'])) {
        header($_SERVER['SERVER_PROTOCOL'].' 412 Precondition Failed', true, 412);
        exit("Upload bestand fout: {$_FILES['afbeelding']['error']}");
    }

    // etcetera, etcetera

    // Could use the default 200 OK, but since that is default and still can show error page,
    // we use a 201 Created so that we really know the file is uploaded and accepted
    header($_SERVER['SERVER_PROTOCOL'].' 201 Created', true, 201);

    print_r(array(
        '$_GET' => $_GET,
        '$_POST' => $_POST,
        '$_FILES' => $_FILES,
    ));
    exit;
}
?>
<!DOCTYPE html>
<html>
<head></head>
<body>

<form id="file-form" action="" method="post" enctype="multipart/form-data">
    Titel: <input name="titel" type="text" />
    <br/>
    Afbeelding: <input name="afbeelding" type="file" />
    <br/>
    <button>Upload</button>
</form>

<script>
var form = document.getElementById("file-form");
if (form) {
    form.onsubmit = function(event) {
        // Get all form fields
        var formData = new FormData(this); // 'this' is the <form> element, because function is called by form element

        // Set up the request.
        var xhr = new XMLHttpRequest();

        // Listen to readystatechange event
        xhr.onreadystatechange = function() {
            // this == xhr, because function is called by xhr
            if (this.readyState == 4) {
                if (201 == this.status) {
                    alert("Upload is klaar! " + xhr.responseText);
                } else {
                    alert("Upload mislukt! " + xhr.responseText);
                }
            }
        }

        // Open the connection.
        // this.action is the <form action=""> element attribute,
        // because function is called by form element
        xhr.open('POST', this.action || document.location.href, true);

        // submit the data
        xhr.send(formData);

        // prevent browser sending the form normally
        event.preventDefault();
        return false; // just to be sure
    }
}
</script>
</body>
</html>


Basisinformatie over HTTP Status codes kan je hier vinden: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

[ Voor 36% gewijzigd door DJMaze op 11-05-2018 23:23 . Reden: PHP code toegevoegd + HTTP Status codes, nu het concept FormData bekend is. ]

Maak je niet druk, dat doet de compressor maar

Alle reacties


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 03-07 17:46

NMe

Quia Ego Sic Dico.

Wat is nou je daadwerkelijke probleem? Je zegt wat je wil, je dumpt wat code en zegt dat er "van alles mis" gaat. Wat dat? Foutmeldingen? Rare resultaten? Wat wil je nou dat wij voor je doen?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
NMe schreef op donderdag 10 mei 2018 @ 22:09:
Wat is nou je daadwerkelijke probleem? Je zegt wat je wil, je dumpt wat code en zegt dat er "van alles mis" gaat. Wat dat? Foutmeldingen? Rare resultaten? Wat wil je nou dat wij voor je doen?
Ik heb dit helaas te vroeg gepublished en was nog helemaal niet klaar.. Maar ik kan blijkbaar geen edits uitvoeren. Ik probeer mijn post dus volledig te maken :)

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 03-07 17:46

NMe

Quia Ego Sic Dico.

BramVanha schreef op donderdag 10 mei 2018 @ 22:10:
[...]

Ik heb dit helaas te vroeg gepublished en was nog helemaal niet klaar.. Maar ik kan blijkbaar geen edits uitvoeren. Ik probeer mijn post dus volledig te maken :)
https://gathering.tweaker...update_message/55160135/0

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
Was net gelukt, ik kreeg eerst een melding dat ik geen bevoegdheid had om te editten. Gereload en werkte wel.

Mijn vraag is nu compleet.

Acties:
  • +1 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 03-07 17:46

NMe

Quia Ego Sic Dico.

Goed, dan verplaats ik nu je topic naar Webdesign, Markup & Clientside Scripting want je probleem speelt volledig aan de clientkant. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Dit kan niet:
JavaScript:
1
2
var f = document.getElementById("fileToUpload").value;
var vars = "f="+f;

Zie https://developer.mozilla...ta/Using_FormData_Objects

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op donderdag 10 mei 2018 @ 22:13:
Dit kan niet:
JavaScript:
1
2
var f = document.getElementById("fileToUpload").value;
var vars = "f="+f;

Zie https://developer.mozilla...ta/Using_FormData_Objects
Ik ben zeer nieuw en dus een echte beginneling, maar bij het vlug even bekijken van die link moet ik al snel afhaken omdat ik het niet echt snap wat er allemaal staat/gebeurt. Wat kan er net niet aan die lijnen code en waarom niet?

Duidt dit dan op het feit dat document.getElementById() enkel een stringwaarde kan doorgeven?

Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
BramVanha schreef op donderdag 10 mei 2018 @ 22:19:
[...]


Ik ben zeer nieuw en dus een echte beginneling, maar bij het vlug even bekijken van die link moet ik al snel afhaken omdat ik het niet echt snap wat er allemaal staat/gebeurt. Wat kan er net niet aan die lijnen code en waarom niet?

Duidt dit dan op het feit dat document.getElementById() enkel een stringwaarde kan doorgeven?
Want ik snap niet zo goed waarom dit dan wel werkt met een gewoon tekstvak?

Acties:
  • +1 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Laatst online: 10:00
Misschien heb je hier wat aan? http://blog.teamtreehouse.com/uploading-files-ajax

Kortgezegd moet je .files ipv .value gebruiken, loopen door alle geselecteerde files en deze appenden aan een nieuw "formData" en de formData dan senden met XmlHTTPRequest.

[ Voor 52% gewijzigd door Ramon op 10-05-2018 22:48 ]

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
Ramon schreef op donderdag 10 mei 2018 @ 22:45:
Misschien heb je hier wat aan? http://blog.teamtreehouse.com/uploading-files-ajax

Kortgezegd moet je .files ipv .value gebruiken, loopen door alle geselecteerde files en deze appenden aan een nieuw "formData" en de formData dan senden met XmlHTTPRequest.
Na kort eventjes door te lezen, denk ik wel dat ik hier iets aan zal hebben. Wel zal het voor morgen zijn aangezien ik nu al de hele dag zit te zoeken op van die kleine dingetjes en het welletjes is geweest voor vandaag.
Ik huilde mezelf bijna in slaap omdat ik er nog maar weinig van verstond maar weet dat ik nu morgen met een hopelijk goede start kan beginnen.

Bedankt!

Acties:
  • 0 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Laatst online: 10:00
Je hoeft jezelf niet in slaap te huilen hoor ;) nergens voor nodig! Als je morgen met die blogpost er niet uit komt dan kan je hier weer terecht! Wel wil ik je dan vragen om een testcase te maken op jsfiddle, dat maakt het voor ons een stuk makkelijker om mee te kijken.

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • +2 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
BramVanha schreef op donderdag 10 mei 2018 @ 22:19:
Ik ben zeer nieuw en dus een echte beginneling, maar bij het vlug even bekijken van die link moet ik al snel afhaken omdat ik het niet echt snap wat er allemaal staat/gebeurt. Wat kan er net niet aan die lijnen code en waarom niet?
Ik vertel je even een historisch verhaaltje:

Vroeger, kon je bij <input type="file"> net als bij alle andere inputs de .value uitlezen en aanpassen.
Daardoor kon je dus de "value" via JavaScript aanpassen in bijvoorbeeld "c:/my-secret-passwords.txt" en zo kon een malafide website bij je bestanden.
Dit is later beveiligd zodat dit niet meer kan.

Zoals je ziet is de waarde van "value" dus de bestandsnaam en niet de inhoud van het bestand.
Je kon dus nooit via XMLHttpRequest bestanden uploaden.

Met XMLHttpRequest v2 kan dat dus wel, maar daarvoor moest er ook iets komen om de data van het bestand te kunnen lezen (op een veilige manier, zie eerste stukje over vroeger).
Hiervoor is dus het .files[] gedeelte (waarom een FileList? dat komt door het "multiple" attribuut).
De bestanden kunnen worden gelezen met FileReader.
Hierdoor zijn er zelfs meer dingen mogelijk! Open https://web.whatsapp.com/ login met je WhatsApp op je telefoon, en sleep vervolgens binnen een chat maar eens een bestand uit je explorer in je browser scherm :)

Het lijkt allemaal heel complex, er is echter vele jaren over nagedacht om de problemen van vroeger te vermijden en alles heel leuk wordt ;)
Je kan nu bijvoorbeeld:
- afbeelding previewen voordat je hem upload (Facebook en web.whatsapp doen dat)
- een upload progress bar tonen (Facebook toont balk, web.whatsapp toont rondje)
- bestand inhoud controleren
- CSV data lezen en een <table> preview met de inhoud
- etc.

Ik begrijp dat het in het begin complex lijkt, echter is het dus expres zodat een malafide script dus niet het volgende kan doen:
code:
1
XMLHttpRequest.send("file=c:/my-secret-passwords.txt");




Echter zie ik een veel crucialer beveiliging probleem. Je PHP function uploadImage() is niet veilig!
Als je op school nog niks hebt geleerd over:
- POSIX vs Win32
- never trust any input
- fake extensions "exploit.php.jpeg" die jouw script dus ziet als afbeelding
- is_uploaded_file($picture['tmp_name'])
- Content-type: image/jpeg via mime_content_type($picture['tmp_name'])

Dan hoop ik, na het uitvoeren van deze opdracht, de leraar je wel iets vertelt over beveiliging.
Zonder uitleg is, in het bedrijfsleven, dit erg gevaarlijk.

[ Voor 24% gewijzigd door DJMaze op 11-05-2018 11:29 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 01:23:
[...]

Ik vertel je even een historisch verhaaltje:

Vroeger, kon je bij <input type="file"> net als bij alle andere inputs de .value uitlezen en aanpassen.
Daardoor kon je dus de "value" via JavaScript aanpassen in bijvoorbeeld "c:/my-secret-passwords.txt" en zo kon een malafide website bij je bestanden.
Dit is later beveiligd zodat dit niet meer kan.

Zoals je ziet is de waarde van "value" dus de bestandsnaam en niet de inhoud van het bestand.
Je kon dus nooit via XMLHttpRequest bestanden uploaden.

Met XMLHttpRequest v2 kan dat dus wel, maar daarvoor moest er ook iets komen om de data van het bestand te kunnen lezen (op een veilige manier, zie eerste stukje over vroeger).
Hiervoor is dus het .files[] gedeelte (waarom een FileList? dat komt door het "multiple" attribuut).
De bestanden kunnen worden gelezen met FileReader.
Hierdoor zijn er zelfs meer dingen mogelijk! Open https://web.whatsapp.com/ login met je WhatsApp op je telefoon, en sleep vervolgens binnen een chat maar eens een bestand uit je explorer in je browser scherm :)

Het lijkt allemaal heel complex, er is echter vele jaren over nagedacht om de problemen van vroeger te vermijden en alles heel leuk wordt ;)
Je kan nu bijvoorbeeld:
- afbeelding previewen voordat je hem upload (Facebook en web.whatsapp doen dat)
- een upload progress bar tonen (Facebook toont balk, web.whatsapp toont rondje)
- bestand inhoud controleren
- CSV data lezen en een <table> preview met de inhoud
- etc.

Ik begrijp dat het in het begin complex lijkt, echter is het dus expres zodat een malafide script dus niet het volgende kan doen:
code:
1
XMLHttpRequest.send("file=c:/my-secret-passwords.txt");




Echter zie ik een veel crucialer beveiliging probleem. Je PHP function uploadImage() is niet veilig!
Als je op school nog niks hebt geleerd over:
- POSIX vs Win32
- never trust any input
- fake extensions "exploit.php.jpeg" die jouw script dus ziet als afbeelding
- is_uploaded_file($picture['tmp_name'])
- Content-type: image/jpeg via mime_content_type($picture['tmp_name'])

Dan hoop ik na het uitvoeren van deze opdracht de leraar je wel iets vertelt over beveiliging.
Zonder uitleg is, in het bedrijfsleven, dit erg gevaarlijk.
Dit verduidelijkt al een heel stuk, waarvoor dank! Ik bekijk het nog even in detail na een andere tutorial die ik nu aan het doornemen ben.

Over de veiligheid moeten wij ons op dit moment nog geen zorgen maken, omdat dit een project is dat we met een groepje volledig moesten uitdenken, van het idee tot de architectuur tot de implementatie. Wel werden we hierin gesmeten en vond ik dat we veel te weinig uitleg gekregen hadden om dit goed te kunnen doen.
Als de gedachtengang en ideeën wel iets leken, kon de onderzoeksgroep van de school hiermee aan de slag en haalden ze alles eruit wat ze konden gebruiken.

Het is zeker belangrijk om die veiligheid in te bouwen, maar daar ga ik me (helaas?) nu niet op focussen aangezien ik dit nog verre van onder de knie heb.

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
BramVanha schreef op vrijdag 11 mei 2018 @ 09:58:
Wel werden we hierin gesmeten en vond ik dat we veel te weinig uitleg gekregen hadden om dit goed te kunnen doen.
Dit gebeurt straks ook zodra je een baan hebt bij een bedrijf.
Zodra je weet hoeveel je moet weten over IT, dan weet je dat je eigenlijk niks weet.
Wat je straks na 10 jaar werken in de IT wel weet, is dat je ALTIJD moet leren en dat school eigenlijk maar een steentje is van de hele berg.
Heb je moeite met zelfstudie/autodidactiek? Dan krijg je het heel zwaar.
Is IT je hobbie en doe/leer je nu ook dingen buiten schooltijd omdat je het leuk vind, dan komt het wel goed.
BramVanha schreef op vrijdag 11 mei 2018 @ 09:58:
Over de veiligheid moeten wij ons op dit moment nog geen zorgen maken, omdat dit een project is dat we met een groepje volledig moesten uitdenken, van het idee tot de architectuur tot de implementatie.

Het is zeker belangrijk om die veiligheid in te bouwen, maar daar ga ik me (helaas?) nu niet op focussen aangezien ik dit nog verre van onder de knie heb.
Ook in het bedrijfsleven staat veiligheid nog steeds niet op plek #1 in het "uitdenk" gedeelte van een project.
Vandaar dat er zoveel nieuws is over gehackte websites en uitgelekte databases met wachtwoorden.

Even mijn afgelopen week:
  • WordPress website gehackt (wachtwoord staat bij haveibeenpwned) en draaide een sshbruteforce.so
  • Magento webshop gehackt bij iemand waardoor mijn persoonlijke gegevens op straat liggen
  • Project overgenomen van een ander IT bedrijf, wachtwoorden in database niet encrypted (alleen bcrypt en argon2i zou mogen)
  • zelf een fout gemaakt in de encryptie van een login cookie (encryptie sleutel was niet uniek, test unit detecteerde dit niet)
  • SQL injectie gevonden in 20 scripts
  • 150 servers geblokkeerd omdat ze Drupal/Joomla websites probeerden aan te vallen
  • 20 servers geblokkeerd omdat ze phishing/virus verstuurden
  • 23 websites ingelicht dat hun websites zijn gehackt
Als school en het bedrijfsleven tijd vrij maken voor beveiliging, heb ik het niet zo druk en kan mij eindelijk richten op mijn normale werk ;)

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
Ik heb nu even de tutorial van "http://blog.teamtreehouse.com/uploading-files-ajax" gevolgd omdat ik er misschien iets aan zou hebben. Helaas zie ik niet in wat die tutorial net als AJAX maakt, want de form wordt gewoon via POST doorgegeven aan een php-file. Met andere woorden; Bij het klikken van de button, opent gewoon de php-pagina en dat is toch niet de bedoeling van AJAX (dynamische website)?

Mijn code na het volgen van de tutorial:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<html>
<head>
    <title>Upload an image</title>
    
    <script>
        var form = document.getElementById('file-form');
        var fileSelect = document.getElementById('file-select');
        var uploadButton = document.getElementById('upload-button');
        
        form.onsubmit = function(event) {
            event.preventDefault();

            // Update button text.
            uploadButton.innerHTML = 'Uploading...';

            // The rest of the code will go here...
        }
        
        // Get the selected files from the input.
        var files = fileSelect.files;
        // Create a new FormData object.
        var formData = new FormData();
        
        // Loop through each of the selected files.
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
                
            // Check the file type.
            if (!file.type.match('image.*')) {
                continue;
        }

            // Add the file to the request.
            formData.append('photos[]', file, file.name);
        }
        
        // Set up the request.
        var xhr = new XMLHttpRequest();
        // Open the connection.
        xhr.open('POST', 'handler.php', true);
        
        // Set up a handler for when the request finishes.
        xhr.onload = function () {
            if (xhr.status === 200) {
            // File(s) uploaded.
            uploadButton.innerHTML = 'Upload';
            } else {
            alert('An error occurred!');
            }
        };
        
        // Send the Data.
        xhr.send(formData);

    </script>
</head>
<body>
    
    <form id="file-form" action="handler.php" method="post">
        <input type="file" id="file-select" name="photos[]" multiple/>
        <button type="submit" id="upload-button">Upload</button>
    </form>
    

</body>

</html>


Doe ik iets verkeerd? Nu wordt alles toch gewoon doorgestuurd via POST, en wordt de php-pagina geopend bij het klikken van de button..?

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Stop je <script> eens onder </body>

Waarom? Dat kan je zien in je webbrowser debug console

[ Voor 45% gewijzigd door DJMaze op 11-05-2018 13:57 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 13:56:
Stop je <script> eens onder </body>

Waarom? Dat kan je zien in je webbrowser debug console
Dat heb ik nu dus gedaan, is daar een reden voor?
EDIT: ik merk op dat er geen nieuwe php-pagina meer geopend wordt nu, maar de html blijft en de button veranderd van tekst naar "Uploading".
Hoe heeft dit script onder de body zetten hier dit effect op gegeven?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<html>
<head>
    <title>Upload an image</title>
</head>
<body>
    
    <form id="file-form" action="handler.php" method="post">
        <input type="file" id="file-select" name="photos[]" multiple/>
        <button type="submit" id="upload-button">Upload</button>
    </form>
    

</body>
    
    <script>
        var form = document.getElementById('file-form');
        var fileSelect = document.getElementById('file-select');
        var uploadButton = document.getElementById('upload-button');
        
        form.onsubmit = function(event) {
            event.preventDefault();

            // Update button text.
            uploadButton.innerHTML = 'Uploading...';

            // The rest of the code will go here...
        }
        
        // Get the selected files from the input.
        var files = fileSelect.files;
        // Create a new FormData object.
        var formData = new FormData();
        
        // Loop through each of the selected files.
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
                
            // Check the file type.
            if (!file.type.match('image.*')) {
                continue;
        }

            // Add the file to the request.
            formData.append('photos[]', file, file.name);
        }
        
        // Set up the request.
        var xhr = new XMLHttpRequest();
        // Open the connection.
        xhr.open('POST', 'handler.php', true);
        
        // Set up a handler for when the request finishes.
        xhr.onload = function () {
            if (xhr.status === 200) {
            // File(s) uploaded.
            uploadButton.innerHTML = 'Upload';
            } else {
            alert('An error occurred!');
            }
        };
        
        // Send the Data.
        xhr.send(formData);

    </script>

</html>

[ Voor 4% gewijzigd door BramCoding op 11-05-2018 14:00 ]


Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
BramVanha schreef op vrijdag 11 mei 2018 @ 13:59:
Dat heb ik nu dus gedaan, is daar een reden voor?
DJMaze schreef op vrijdag 11 mei 2018 @ 13:56:
Waarom? Dat kan je zien in je webbrowser debug console
Heb je debuggen ook nog niet gehad op school?

Afbeeldingslocatie: https://tweakers.net/ext/f/CfkccgOkm7IK340XS3NDadA9/full.png

[ Voor 10% gewijzigd door DJMaze op 11-05-2018 14:07 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 14:03:
[...]


[...]

Heb je debuggen ook nog niet gehad op school?
Nee daar zien wij helemaal niets van. We zien een inleiding op HTML, CSS, PHP en Javascript. Dan krijgen we een project en we moeten het maar tot een goed einde brengen.

Zoals je merkt ben ik echt onervaren en weet ik nog heel veel niet, maar een project van "deze grootte" meteen krijgen vind ik persoonlijk geen goede opdracht. Veel te weinig achtergrond in het web-gedeelte.

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
@BramVanha ik heb een screenshot toegevoegd. Zoek die maar eens in je eigen webbrowser ;)

Dat je onervaren bent weet ik wel.
Zodra iemand zegt "voor/op school" dan weet ik eigenlijk al dat iemand de basis nog niet weet.

Daarnaast is zelfstudie in dit vak essentieel tot aan je pensioen.
Dat school je in het diepe gooit is dus net als in het bedrijfsleven :p

Vroeger toen debug console's nog niet bestonden (jaren 90) was mijn enige redmiddel
JavaScript:
1
2
3
4
5
6
try {
    // al mijn code hier
}
catch (err) {
    alert(err.message);
}
En dan op zoek in je code "waar" het probleem überhaupt vandaan kwam |:(

En toen volgde ik niet eens een IT opleiding. In 1995 ging ik gewoon op mijn kamertje zelf aan de stoei en later in 1997 met een boek: https://www.amazon.com/Of...programmers/dp/1566046750
Dat boek heb ik trouwens niet meer, dat is volgens mij bij heel veel studenten door hun handen gegaan en zwerft nu vast ergens bij iemand in de kast.

[ Voor 107% gewijzigd door DJMaze op 11-05-2018 14:22 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 14:09:
@BramVanha ik heb een screenshot toegevoegd. Zoek die maar eens in je eigen webbrowser ;)

Dat je onervaren bent weet ik wel.
Zodra iemand zegt "voor/op school" dan weet ik eigenlijk al dat iemand de basis nog niet weet.

Daarnaast is zelfstudie in dit vak essentieel tot aan je pensioen.
Dat school je in het diepe gooit is dus net als in het bedrijfsleven :p

Vroeger toen debug console's nog niet bestonden (jaren 90) was mijn enige redmiddel
JavaScript:
1
2
3
4
5
6
try {
    // al mijn code hier
}
catch (err) {
    alert(err.message);
}
En dan op zoek in je code "waar" het probleem überhaupt vandaan kwam |:(

En toen volgde ik niet eens een IT opleiding. In 1995 ging ik gewoon op mijn kamertje zelf aan de stoei en later in 1997 met een boek: https://www.amazon.com/Of...programmers/dp/1566046750
Dat boek heb ik trouwens niet meer, dat is volgens mij bij heel veel studenten door hun handen gegaan en zwerft nu vast ergens bij iemand in de kast.
Ik snap inderdaad wel dat de beste leerschool gewoon proberen en zoeken is. Helaas zoek ik nu al enkele lange uren achter een simpele oplossing voor iets wat ik wil doen maar heb ik het nog steeds niet uitgepluist 8)7 . Nu ja, ik zoek hard verder want mijn project is verre van al af en ik wil dit niet graag in herexamen nemen.

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
@BramVanha is het een eis in de opdracht of heb je het zelf bedacht?
Eigen inzet wordt gewaardeerd, ook in het bedrijfsleven, mits.. het geen extra uren/geld kost!

Het laatste wat je wil is namelijk: tijdsnood

En trust me: tijdsnood is een algemeen goed in IT en een burn-out ligt op de loer.
Het is ook fijn als je tijd overhoud voor een dansje en een drankje met je vrienden.

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 14:31:
@BramVanha is het een eis in de opdracht of heb je het zelf bedacht?
Eigen inzet wordt gewaardeerd, ook in het bedrijfsleven, mits.. het geen extra uren/geld kost!

Het laatste wat je wil is namelijk: tijdsnood

En trust me: tijdsnood is een algemeen goed in IT en een burn-out ligt op de loer.
Het is ook fijn als je tijd overhoud voor een dansje en een drankje met je vrienden.
Het is een eis in de opdracht maar dit is slechts een klein deeltje. Maar het is wel noodzakelijk, vandaar dat ik dit écht werkende wil krijgen.
Ik blijf alvast verder zoeken en "prutsen"!

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Alles is in den beginne serieel: eerst dit, dan dat.

"form is null" komt dus omdat je eerst zoekt op document.getElementById('file-form');
maar deze staat er helemaal niet boven, die staat er onder.

Doe dus eerst dit: <form id="file-form">
Daarna doe je dat: document.getElementById('file-form');

Ingewikkelder:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<head>
<script>
  // Stap 1
  document.addEventListener("DOMContentLoaded", function(event) {
    // Stap 3
    console.log(document.getElementById('file-form'));
  });
</script>
</head>

<body>
<!-- Stap 2 -->
<form id="file-form">
</form>
</body>

Stap 1: zeg tegen JavaScript dat het de functie moet uitvoeren zodra alle html is geladen
Stap 2: definieer alles in je html
Stap 3: JavaScript voert nu de functie uit die in stap 1 is opgegeven

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 14:57:
Alles is in den beginne serieel: eerst dit, dan dat.

"form is null" komt dus omdat je eerst zoekt op document.getElementById('file-form');
maar deze staat er helemaal niet boven, die staat er onder.

Doe dus eerst dit: <form id="file-form">
Daarna doe je dat: document.getElementById('file-form');

Ingewikkelder:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<head>
<script>
  // Stap 1
  document.addEventListener("DOMContentLoaded", function(event) {
    // Stap 3
    console.log(document.getElementById('file-form'));
  });
</script>
</head>

<body>
<!-- Stap 2 -->
<form id="file-form">
</form>
</body>

Stap 1: zeg tegen JavaScript dat het de functie moet uitvoeren zodra alle html is geladen
Stap 2: definieer alles in je html
Stap 3: JavaScript voert nu de functie uit die in stap 1 is opgegeven
Nu snap ik het helemaal niet meer. Nu staat mijn script toch weer boven de body? Je raadde me aan om dit onder de body te zetten een paar posts terug?
Ik vind zoveel tutorials online over mijn probleem, maar geen enkele werkt of toont alles. Dus ik probeer nu allemaal dingen aan elkaar te hangen maar zoals verwacht schuift dit voor geen millimeter |:(

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Hahaha, logica is nog niet je sterkste vak merk ik.

Trek je eerst je schoenen aan en dan je sokken, of eerst je sokken en dan je schoenen?
Nu zijn je schoenen de JavaScript (het technische wat steeds doorloopt), en je sokken de HTML.
Wat is het resultaat in deze vergelijking, en wat is het meest logische?

Nou, dat is de uitkomst van "Je raadde me aan om dit onder de body te zetten een paar posts terug".

De laatste ingewikkelde post "Nu staat mijn script toch weer boven de body" moet je zo zien:

head: jouw hoofd zegt addEventListener("trek mijn schoenen aan nadat ik mijn kleren aan heb")
body: hey head, ik heb mijn kleren aan! (event: DOMContentLoaded)
head: mooi ga ik nu mijn schoenen aantrekken

offtopic:
Damn wat zijn HTML tags toch leuk te betrekken op eigen lichaam :+

[ Voor 6% gewijzigd door DJMaze op 11-05-2018 15:20 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 15:14:
Hahaha, logica is nog niet je sterkste vak merk ik.

Trek je eerst je schoenen aan en dan je sokken, of eerst je sokken en dan je schoenen?
Nu zijn je schoenen de JavaScript (het technische wat steeds doorloopt), en je sokken de HTML.
Wat is het resultaat in deze vergelijking, en wat is het meest logische?

Nou, dat is de uitkomst van "Je raadde me aan om dit onder de body te zetten een paar posts terug".

De laatste ingewikkelde post "Nu staat mijn script toch weer boven de body" moet je zo zien:

head: jouw hoofd zegt addEventListener("trek mijn schoenen aan nadat ik mijn kleren aan heb")
body: hey head, ik heb mijn kleren aan! (event: DOMContentLoaded)
head: mooi ga ik nu mijn schoenen aantrekken

offtopic:
Damn wat zijn HTML tags toch leuk te betrekken op eigen lichaam :+
Oke ik zie waarom dit mag, verstond niet zo goed wat die DOMContentLoaded eigenlijk was.
Ik ben terug bezig met mijn nu reeds twintigste tutorial te volgen, versta er weer weinig van, maar we zien wel wat copy paste geeft O-)

Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
BramVanha schreef op vrijdag 11 mei 2018 @ 15:06:
Ik vind zoveel tutorials online over mijn probleem, maar geen enkele werkt of toont alles. Dus ik probeer nu allemaal dingen aan elkaar te hangen maar zoals verwacht schuift dit voor geen millimeter |:(
Dat komt omdat ze erg uitgebreid zijn.

Dit is de meest minimale basis:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php
if ('POST' === $_SERVER['REQUEST_METHOD']) {
    if (!isset($_FILES['afbeelding'])) {
        header($_SERVER['SERVER_PROTOCOL'].' 412 Precondition Failed', true, 412);
        exit('Er ging iets mis met het formulier');
    }
    if (!empty($_FILES['afbeelding']['error'])) {
        header($_SERVER['SERVER_PROTOCOL'].' 412 Precondition Failed', true, 412);
        exit("Upload bestand fout: {$_FILES['afbeelding']['error']}");
    }

    // etcetera, etcetera

    // Could use the default 200 OK, but since that is default and still can show error page,
    // we use a 201 Created so that we really know the file is uploaded and accepted
    header($_SERVER['SERVER_PROTOCOL'].' 201 Created', true, 201);

    print_r(array(
        '$_GET' => $_GET,
        '$_POST' => $_POST,
        '$_FILES' => $_FILES,
    ));
    exit;
}
?>
<!DOCTYPE html>
<html>
<head></head>
<body>

<form id="file-form" action="" method="post" enctype="multipart/form-data">
    Titel: <input name="titel" type="text" />
    <br/>
    Afbeelding: <input name="afbeelding" type="file" />
    <br/>
    <button>Upload</button>
</form>

<script>
var form = document.getElementById("file-form");
if (form) {
    form.onsubmit = function(event) {
        // Get all form fields
        var formData = new FormData(this); // 'this' is the <form> element, because function is called by form element

        // Set up the request.
        var xhr = new XMLHttpRequest();

        // Listen to readystatechange event
        xhr.onreadystatechange = function() {
            // this == xhr, because function is called by xhr
            if (this.readyState == 4) {
                if (201 == this.status) {
                    alert("Upload is klaar! " + xhr.responseText);
                } else {
                    alert("Upload mislukt! " + xhr.responseText);
                }
            }
        }

        // Open the connection.
        // this.action is the <form action=""> element attribute,
        // because function is called by form element
        xhr.open('POST', this.action || document.location.href, true);

        // submit the data
        xhr.send(formData);

        // prevent browser sending the form normally
        event.preventDefault();
        return false; // just to be sure
    }
}
</script>
</body>
</html>


Basisinformatie over HTTP Status codes kan je hier vinden: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

[ Voor 36% gewijzigd door DJMaze op 11-05-2018 23:23 . Reden: PHP code toegevoegd + HTTP Status codes, nu het concept FormData bekend is. ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 16:04:
[...]

Dat komt omdat ze erg uitgebreid zijn.

Dit is de meest minimale basis:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<form id="file-form" action="handler.php" method="post" enctype="multipart/form-data">
</form>

<script>
var form = document.getElementById("file-form");
if (form) {
    form.onsubmit = function(event) {
        event.preventDefault();

        // Get all form fields
        var formData = new FormData(this); // this is the <form> element, because function is called by form element

        // Set up the request.
        var xhr = new XMLHttpRequest();

        // Listen to readystatechange event
        xhr.onreadystatechange = function() {
            // this == xhr, because function is called by xhr
            if (this.readyState == 4) {
                if (200 == this.status) {
                    alert("Upload is klaar! " + xhr.responseText);
                } else {
                    alert("Upload mislukt! " + xhr.responseText);
                }
            }
        }

        // Open the connection.
        // this.action is the <form action=""> element attribute,
        // because function is called by form element
        xhr.open('POST', this.action || document.location.href, true);

        // submit the data
        xhr.send(formData);
    }
}
</script>
Ik had nu al iets dat daar heel hard op lijkt, dus ik blijk toch op de goeie weg te zijn. Ik denk dat het dan eerder misloopt in het uitlezen van die "formData". Ik zocht al wat uit hoe ik dat FormData-object nu moest uitlezen in de php-file waar het naartoe gestuurd werd, maar liep ook telkens vast.

Ik zoek hier wel nog even op verder.

Als ik het goed heb dan is die formData dus een verzameling van alle form-elementen gebundeld in mijn form met id "file-form"? Dus dan wordt in 1 keer een foto maar ook bvb een bijhorende tekst doorgestuurd naar de php-file?

Als dit correct is, dan moet ik enkel nog maar uitzoeken hoe die formData nu moet uitgelezen worden in de php-file waar hij naartoe gestuurd werd, om dan hopelijk wel $_FILES[] te kunnen gebruiken om zo via
code:
1
move_uploaded_file($_FILES[$mijnUploadedPicture]["tmp_name"], path)
de image te kunnen opslaan op mijn lokale webserver.

Ik wil je alvast terug danken voor je geduld en hulp met mij, het moet soms frustrerend zijn om iemand onervaren zelf de meest simpele dingen bij te brengen.. _/-\o_

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Simpel? Je mist de basis, vandaar dat je ruzie maakt met XMLHttpRequest ;)

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 16:17:
Simpel? Je mist de basis, vandaar dat je ruzie maakt met XMLHttpRequest ;)
Klopt, en ik ben al een beetje wijzer mede door jouw hulp. Is de rest wat ik dan zei in vorige post correct of maak ik nog grote fouten in mijn gedachtengang bij jouw code?

Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
EDIT: mijn plaatjes willen niet laden via Gyazo, maar de link werkt wel gewoon :)

Ik heb de code van u dus nog een klein beetje extra uitgebreid, en de alert dat de upload gelukt is komt er op, dus ik veronderstel dat de XMLHttpRequest correct verzonden is naar de "handler.php".

Echter wil ik dit dus nu checken via debugger. Hoe precies kan ik nu zien wat er naar de "handler.php" gestuurd werd? Ik doe dus rechtermuis en klik dan op "inspecteren", dan ga ik naar tabblad "Netwerk". Als ik op de knop druk, dan komt mijn "handler.php" tevoorschijn, maar uit die gegevens weet ik niet zo goed wat er net gebeurt;
Afbeeldingslocatie: https://gyazo.com/6c9ab71e75056d5e59a63de5799dc7ca
Afbeeldingslocatie: https://gyazo.com/5c946cbb9dcf19ab044f0f9587da0806

Mag ik uit de onderste screenshot afleiden dat de foto "apple.png" correct doorgegaan is? Ik denk van wel aan het "Request Payload"-deel bij "headers" als ik op de "handler.php" klik wanneer die tevoorschijn gekomen is na het klikken van de button.

Dit is de code die ik ervoor gebruik (uw code dus):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<html>
<head>
    <title>Upload an image</title>
</head>
<body>
    
    <form id="uploadForm" action="handler.php" method="post" enctype="multipart/form-data">
        <input type='file' id="fileToUpload" name="fileToUpload" accept ="image/*"/>
        <button type="submit" id="uploadButton" name="uploadButton">Upload image</button> 
    
    </form>

    <script>
    var form = document.getElementById("uploadForm");
    if (form) {
        form.onsubmit = function(event) {
            // Get all form fields
            var formData = new FormData(this); // this is the <form> element, because function is called by form element

            // Set up the request.
            var xhr = new XMLHttpRequest();

            // Listen to readystatechange event
            xhr.onreadystatechange = function() {
                // this == xhr, because function is called by xhr
                if (this.readyState == 4) {
                    if (200 == this.status) {
                        alert("Upload is klaar! " + xhr.responseText);
                    } else {
                        alert("Upload mislukt! " + xhr.responseText);
                    }
                }
            }

            // Open the connection.
            // this.action is the <form action=""> element attribute,
            // because function is called by form element
            xhr.open('POST', this.action || document.location.href, true);

            // submit the data
            xhr.send(formData);

            // prevent browser sending the form normally
            event.preventDefault();
            return false; // just to be sure
        }
    }
    </script>
    
</body>
    
    
</html>

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Je bent op de goede weg.
Om die reden heb ik mijn vorige post aangepast en wat PHP code toegevoegd ;)

Tevens heb ik wat HTTP Status Codes toegevoegd en gezorgd dat je bij een goede upload 201 moet gebruiken i.p.v. 200
Hierdoor merk je beter of het goed/fout gaat

DJMaze in "Image upload via AJAX/html/php"

[ Voor 60% gewijzigd door DJMaze op 11-05-2018 23:25 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op vrijdag 11 mei 2018 @ 20:32:
Je bent op de goede weg.
Om die reden heb ik mijn vorige post aangepast en wat PHP code toegevoegd ;)

Tevens heb ik wat HTTP Status Codes toegevoegd en gezorgd dat je bij een goede upload 201 moet gebruiken i.p.v. 200
Hierdoor merk je beter of het goed/fout gaat

DJMaze in "Image upload via AJAX/html/php"
Ik heb die PHP code gebruikt en aangepast naar mijn name's natuurlijk. De foto wordt correct doorgezonden denk ik, want ik krijg een melding: Afbeeldingslocatie: https://gyazo.com/5b277adf35d5a205234a2fc2a38d398a.

Ook als ik het titelvakje invul dan komt deze in de $_POST te staan, dus dat werkt ook.
Nu kan ik dus in mijn php alles opvangen door $_POST["titel"] of bvb $_FILES["fileToUpload"] te gebruiken en daarmee kan ik normaal terug aan de slag.

Wel nog een vraagje:
code:
1
if ('POST' === $_SERVER['REQUEST_METHOD']) { }
--> is dit de code die kijkt of er een FormData-element werd gestuurd vanuit een html-file? En als dit zo is, dan gaat hij de binnenste structuren uitvoeren natuurlijk, maar zolang er geen FormData doorgestuurd werd, zal deze niets doen?

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
BramVanha schreef op zaterdag 12 mei 2018 @ 11:17:
is dit de code die kijkt of er een FormData-element werd gestuurd vanuit een html-file?
Nee. Lees https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods

<form method="get"> = stopt alle form velden in de adresbalk: bestand.php?input1=value1&input2=value2&etc.

<form method="post"> = stopt alle form velden in de mime body

<form method="delete"> = verwijdert het bestand op de server

Er wordt dus puur gekeken of je überhaupt POST.
Als de $_SERVER['REQUEST_METHOD'] iets anders is, moet je gewoon niks doen.

Dit is basis HTTP, ook nog niet gehad op school zeker?

Als je handler.php alleen maar POST requests afhandelt kan je ook dit doen:
PHP:
1
2
3
4
5
6
7
<?php
// Only allow POST requests
if ('POST' !== $_SERVER['REQUEST_METHOD']) {
    header($_SERVER['SERVER_PROTOCOL'].' 405 Method Not Allowed', true, 405);
    header('Allow: POST');
    exit("Method {$_SERVER['REQUEST_METHOD']} is not allowed");
}


Stel je snapt niks van HEAD requests en je script accepteert GET en POST
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
// Only allow GET and POST requests
$allowed_methods = array('GET', 'POST');
if ('OPTIONS' === $_SERVER['REQUEST_METHOD'] {
    header('Allow: '.implode(', ', $allowed_methods));
    exit;
}
if (!in_array($_SERVER['REQUEST_METHOD'], $allowed_methods)) {
    header($_SERVER['SERVER_PROTOCOL'].' 405 Method Not Allowed', true, 405);
    header('Allow: '.implode(', ', $allowed_methods));
    exit("Method {$_SERVER['REQUEST_METHOD']} is not allowed");
}

[ Voor 40% gewijzigd door DJMaze op 12-05-2018 12:10 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
DJMaze schreef op zaterdag 12 mei 2018 @ 11:30:
[...]

Nee. Lees https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods

<form method="get"> = stopt alle form velden in de adresbalk: bestand.php?input1=value1&input2=value2&etc.

<form method="post"> = stopt alle form velden in de mime body

<form method="delete"> = verwijdert het bestand op de server

Er wordt dus puur gekeken of je überhaupt POST.
Als de $_SERVER['REQUEST_METHOD'] iets anders is, moet je gewoon niks doen.

Dit is basis HTTP, ook nog niet gehad op school zeker?

Als je handler.php alleen maar POST requests afhandelt kan je ook dit doen:
PHP:
1
2
3
4
5
6
7
<?php
// Only allow POST requests
if ('POST' !== $_SERVER['REQUEST_METHOD']) {
    header($_SERVER['SERVER_PROTOCOL'].' 405 Method Not Allowed', true, 405);
    header('Allow: POST');
    exit("Method {$_SERVER['REQUEST_METHOD']} is not allowed");
}
Haha, nope, dit vak heet Webtech, en we zien een inleiding HTML, CSS, PHP en ietsiemini beetje JavaScript. Dan vooral syntax en voorbeelden als "een tekstvak maken" en via POST uitlezen in een PHP.
Maar ik heb toch al iets bijgeleerd (mede door jou) en lezen/zoeken.

Bedankt voor de nogmaalse opklaring :)

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
@BramVanha oeh, dan is de opdracht inderdaad best pittig.

Klinkt als: nou kijk in het boek staat een fiets. Opdracht: maak een fiets

P.S. je hoeft niet steeds mijn hele bericht te quoten dat is erg vervuilend ;)

[ Voor 23% gewijzigd door DJMaze op 12-05-2018 12:13 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
@DJMaze Dan bedoel je dat ik het op deze manier doe? :D

Ja de opdracht is best wel pittig voor de kennis die we naar mijn gevoel hebben. Er zitten wel studenten die reeds een achtergrond hebben hierin, maar voor de newbies is het wel tijdsrovend.
Ik ben alvast van plan om hier eens een deftig boek over te lezen als ik wat meer vrije tijd heb (lees na de examenperiode die er aan komt).

Ik ben de FormData-elementen die verstuurd werden nu aan het opvangen in de PHP-file, en dan is de bedoeling dat de image upgeload wordt naar de lokale webserver, maar dat had ik al gekunnen via een gewone POST uit de html naar de php, dus moet nu ook wel doenbaar zijn. Dan neem ik de link naar deze foto en stop hem in een mySQL database. Ook dat is me al eens gelukt dus zou dit (hopelijk) geen nieuwe problemen mogen geven.

Acties:
  • +2 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Laatst online: 10:00
Maar staat er echt in de opdracht dat het met AJAX moet? Zo nee dan maak je het jezelf natuurlijk wel nodeloos ingewikkeld....

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
@Ramon Neen, maar als je op "upload image" klikt, moet er wel dynamisch een message komen die je meedeelt als alles goed is gegaan, of er fouten opgedoken zijn.

Na wat opzoeken kwam ik bij AJAX terecht, om zo "makkelijk" (eenmaal je ermee weg bent) dynamisch te werk te gaan.

Nu het lijkt bijna te lukken, en ik heb er dan wel te veel tijd naar mijn zin moeten insteken, maar uiteindelijk ben ik dan wel blij dat het gelukt zal zijn.

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
DJMaze schreef op vrijdag 11 mei 2018 @ 14:31:
is het een eis in de opdracht of heb je het zelf bedacht?
BramVanha schreef op vrijdag 11 mei 2018 @ 14:34:
Het is een eis in de opdracht maar dit is slechts een klein deeltje. Maar het is wel noodzakelijk, vandaar dat ik dit écht werkende wil krijgen.
Ramon schreef op zaterdag 12 mei 2018 @ 12:40:
Maar staat er echt in de opdracht dat het met AJAX moet?
BramVanha schreef op zaterdag 12 mei 2018 @ 12:42:
@Ramon Neen, maar als je op "upload image" klikt, moet er wel dynamisch een message komen die je meedeelt als alles goed is gegaan, of er fouten opgedoken zijn.
@Ramon damn, jouw manier van vragen geeft een beter antwoord dan mijn versie _/-\o_

Je hebt dus helemaal geen JavaScript nodig.
"dynamisch" kon net zo goed een je-bestand-is-geupload.html zijn.
Denk ook eerder dat de leraar dat er mee bedoelde.
Het staat dan waarschijnlijk wel onduidelijk in de opdracht.

Iets als:
  1. upload afbeelding
  2. toon een pagina waarop wordt gemeld dat het uploaden is gelukt of mislukt

[ Voor 13% gewijzigd door DJMaze op 12-05-2018 14:31 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
@DJMaze maar dan laadt een nieuwe pagina, namelijk de "je-bestand-is-geupload.html"-pagina. En dit wil mocht net niet, de pagina moest dezelfde blijven als waarin de knop en form zich bevindt.

Ik gebruik het woord "dynamisch" verkeer dan gok ik.

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Ah dus:
  1. upload afbeelding
  2. toon op de zelfde pagina een melding dat het uploaden is gelukt of mislukt

[ Voor 177% gewijzigd door DJMaze op 12-05-2018 14:40 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
@DJMaze Klopt. De afbeelding in de php dan verwerken, uploaden naar de webserver, de link ervan in de database schrijven (en dan nog 5 extra velden zoals info bij de image, ..), en dan zonder de pagina te hoeven refreshen en op dezelfde pagina een bericht te zien of het gelukt is, mislukt, wat er net mislukt is,...

Kon dit makkelijker zonder AJAX misschien? Oeps

AJAX was hetgeen ik veel tegenkwam en ik dus dacht the way to go was..

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
BramVanha schreef op zaterdag 12 mei 2018 @ 14:38:
Kon dit makkelijker zonder AJAX misschien? Oeps
Ja:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
$success = $error = false;
if ('POST' === $_SERVER['REQUEST_METHOD']) {
    if (!isset($_FILES['afbeelding'])) {
        $error = 'Er ging iets mis met het formulier';
    }
    else if (!empty($_FILES['afbeelding']['error'])) {
        $error = "Upload bestand fout: {$_FILES['afbeelding']['error']}";
    }

    // etcetera, etcetera
        
    if ($error) {
        header($_SERVER['SERVER_PROTOCOL'].' 412 Precondition Failed', true, 412);
    }
    $success = !$error;
}
?>
<!DOCTYPE html>
<html>
<head></head>
<body>

<?php
// Dit is dus "dynamisch"
if ($error) {
?>
    <h1 style="color:#F00">Het uploaden is mislukt!</h1>
    <?php echo htmlspecialchars($error); ?>
<?php
} else if ($success) {
?>
    <h1 style="color:#0F0">Het uploaden is gelukt!</h1>
<?php
}
?>


<form id="file-form" action="" method="post" enctype="multipart/form-data">
    Titel: <input name="titel" type="text" />
    <br/>
    Afbeelding: <input name="afbeelding" type="file" />
    <br/>
    <button>Upload</button>
</form>

</body>
</html>

[ Voor 15% gewijzigd door DJMaze op 12-05-2018 14:49 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • +1 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Laatst online: 10:00
Als je het hebt over PHP dan wordt dat ook vaak met "dynamisch" aangeduid, dus ja afhankelijk van de vraagstelling was dat waarschijnlijk ook goed geweest.

Wikipedia: PHP

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
Hmm, dan weet ik niet zo goed wat AJAX net te bieden heeft, maar ik heb het nu wel werkende gekregen dus we zijn al een stap verder.. :p

Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
@BramVanha dmv AJAX hoef je niet hele pagina's in te laden.
Stel je hebt een website zoals tweakers en een forum pagina zoals deze met bergen toeters en bellen.
Nu plaats ik een reactie, dan is het zonde om de server te belasten met heel veel code om deze pagina te "vernieuwen".
Nou dan gebruik je AJAX om alleen net die ene nieuwe post te tonen.
Scheelt een hoop!

In jouw geval hoeft AJAX alleen "gelukt"/"mislukt" terug te sturen i.p.v. alle HTML.

[ Voor 10% gewijzigd door DJMaze op 12-05-2018 20:11 ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
@DJMaze Ah oke, ik snap het. Dat maakt AJAX inderdaad wel handig voor grotere pagina's.
Nu, zo heb ik al wat ervaring opgedaan voor als ik het later nog tegen kom.

Hartelijk dank!

Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
Volgende (hopelijk) kleinere probleempje;

met deze AJAX-request structuur die ik nu heb, wil ik graag in mijn PHP-form waar deze gegevens toekomen kijken of de knop ingedrukt werd. Als dit zo is moet er iets gebeuren. Voor gewone waardes ging ik als volgt te werk:

code:
1
if (isset($_POST['naamwaarde])) {............ code wat er moet gebeuren ...........}


Maar als ik dit doe met een button, dus:
code:
1
if (isset($_POST['buttonname])) {............ code wat er moet gebeuren ...........}


Dan werkt dit helaas niet. De click van de button wordt niet opgevangen dan. Is er een anderen manier om deze buttonclick te detecteren (in de structuur die ik nu al heb).

Of is het makkelijkst om in mijn PHP-file te controleren of alle input-fields horende bij de button ingevuld zijn? Iets zoals dit:
code:
1
if (isset($_POST['metadata']) && isset($_POST['longitude']) && isset($_POST['latitude'])){... code uit te voeren.....}


Kan ik uberhaupt een buttonclick detecteren via de FormData die verzonden wordt, aangezien in de html-file in het script eigenlijk de button click al opgevangen wordt en dan pas de FormData verstuurd wordt?

Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
Nog een opvolgende vraag:

bij het terug opvangen van de response van de XMLHttpRequest, kan ik dan ook de reponse laten printen in bvb een andere html-pagina?
code:
1
document.getElementById("status").innerHTML = xhr.responseText;

Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
En een derde bijkomende vraag:

als ik nu binnenin mijn PHP na het uitvoeren van een deel code een nieuwe pagina wil openen, dan gaat dit normaal via
code:
1
header("Location: index.html");
.

Dit werkt als ik niet via AJAX werk, maar gewoon via een PHP-POST. Van zodra ik mijn AJAX script uit commentaar haal, dan opent hij die nieuwe pagina niet volledig en blijft mijn huidige pagina ook staan. Dan krijg ik dit: Afbeeldingslocatie: https://gyazo.com/9850473a6ae3a22b82f8d4f5caf3fa5a.
Vanaf het blauwe is mijn nieuwe pagina.

Hoe komt het dat door dit AJAX-script aan te zetten dat deze header(LOCATION: ) plots niet meer werkt?

Acties:
  • 0 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Laatst online: 10:00
@BramVanha Als je dat doet, wat is dan nog het nut van AJAX? Dan ga je dus eerst met ajax je afbeelding uploaden en dan de browser naar een andere pagina doorsturen? Dat is dan toch exact hetzelfde als de afbeelding niet met AJAX uploaden?

Maar om antwoord te geven op je vraag, als je de browser wil doorsturen naar een andere pagina met JavaScript dan kan je dat doen met https://developer.mozilla...s/Web/API/Window/location

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
@Ramon Ik heb een MVC-patroon, en de controller is dus mijn opvangende PHP-file.
Bij sommige formulieren moet er gewoon iets teruggegeven worden, bij sommige iets teruggegeven en dan doorverwezen naar een andere pagina, bij sommige geen teruggavemessage maar gewoon doorverwijzing naar een andere pagina.

Vandaar dat ik even mijn opties aan het bekijken ben hoe ik dit allemaal kan doen..
Ik weet dat mijn project niet "slim" geïmplementeerd zal zijn, zo alles door elkaar, maar de weinige tijd en ervaring laten mij op dit moment weinig anders toe.

Ik lees deze link eens in die u gaf, en kijk wat ik eruit kan halen :D

Acties:
  • 0 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Laatst online: 10:00
Wat je kan doen is je PHP script JSON laten retourneren die instructies bevat voor wat de javascript ermee moet doen.

Bijvoorbeeld zo:
code:
1
{"redirect_to": "index.html"}

In je JavaScript kijk je dan of er een "redirect_to" instructie is, en zo ja, dan gebruik je de bovenstaande window.location en zo nee dan doe je niets.

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 11-02 10:26
@Ramon Dat bekijk is zometeen even, bedankt!
Pagina: 1