upload file from browser to SD card

Hey all,
I have a functioning web server using a Mega w/Ethernet shield. I can serve pages and respond to AJAX requests just fine.

I would like to add the ability to update the CSS file (or any other file) on the sd card from the browser. I am pretty sure I can handle parsing the file data once it gets to the arduino, but I am rather stuck on the html/java script side. I know how to upload files to php, but running php in the arduino doesn't seem like an option. Maybe this isn't an arduino question, but I not sure where else to ask for help.

I have done quite a bit of googling around and have tried many different implementations, yet I still have no working solutions.

Any help?

Some black magic: bash, cgi and file uploads :wink:

update_20150203.zip (29.8 KB)

I'm not sure I'm going to be able to run cgi scripts in a Mega.
Anyone else?

Look for SurferTim's page on FTP using the Arduino. It covers uploading and downloading files to and from the Arduino as server.

http://playground.arduino.cc/Code/FTP

cgi script - just an example how to get file header and file data. If you can get stream from the client so you can read a file.
Using javascript and ajax you can divide whole file on small pieces and send them to arduino.

Using javascript and ajax you can divide whole file on small pieces and send them to arduino.

Can you show me with an example? The is the exact part I am stuck on.

See attached archive (update folder). main.html and main.js do that. But I don't know how to define the size of piece.

function uploadFile() {

var fd = new FormData();

fd.append( "fileToUpload", document.getElementById('fileToUpload').files[0] );

var xhr = new XMLHttpRequest();

xhr.upload.addEventListener( "progress", uploadProgress, false );
xhr.addEventListener( "load", uploadComplete, false );
xhr.addEventListener( "error", uploadFailed, false );
xhr.addEventListener( "abort", uploadCanceled, false );

xhr.open( "POST", "/cgi-bin/modules/update/action.cgi" );

xhr.send( fd );

}

One more example: Uploading File Using XMLHttpRequest Level 2

ok.. thanks for the example... It would appear that I'll be taking baby steps to achieve this.

This is my html/js code

<!DOCTYPE html>

<html>
<body>

 <div id="status">status</div>
 


    <input type="file" id="fileInput"/>
    <button onclick="startUpload();">Upload</button>
    

    <progress id="progressBar" max="100" value="0"/>

</body>
</html>
<script>


function startUpload() {
    var fileInput = document.getElementById("fileInput");

    if (fileInput.files.length == 0) {
        alert("Please choose a file");
        return;
    }
    
    var progressBar = document.getElementById("progressBar");
    var xhr = new XMLHttpRequest();

    xhr.upload.onprogress = function(e) {
        var percentComplete = (e.loaded / e.total) * 100;
        progressBar.value = percentComplete;
    };

    xhr.onload = function() {
        if (xhr.status == 200) {
            alert("Sucess! Upload completed");
        } else {
            alert("Error! Upload failed");
        }
    };
    xhr.onerror = function() {
        alert("Error! Upload failed. Can not connect to server.");
    };
    
    progressBar.value = 0;
    xhr.open("POST", "ajax-upload", true);
    xhr.setRequestHeader("Content-Type", fileInput.files[0].type);
    xhr.send(fileInput.files[0]);
}
</script>

And this is the relevant code in the arduino...

void checkForClient()
{
  EthernetClient client = server.available();  // try to get client
  if (client)
  { // got client?

    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {   // client data available to read
        char c = client.read(); // read 1 byte (character) from client
 Serial.print(c);
//blah
//blah
//blah

When I upload the file to the arduino, the ethernet client receives the following...

POST /ajax-upload HTTP/1.1
Host: 192.168.1.178
Connection: keep-alive
Content-Length: 16
Origin: http://192.168.1.178
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
Content-Type: text/plain
Accept: /
Referer: http://192.168.1.178/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8

the file contains the text "THIS iS the FILE", but I don't see it anywhere in what the arduino receives so I guess the file contents is not being sent or I am missing it some how.

Is there anything specific I need to do on the arduino end to get the file contents?

No I'm sorry my bad....

After cutting my arduino code back, here is the everything received by the arduino...

POST /ajax-upload HTTP/1.1
Host: 192.168.1.178
Connection: keep-alive
Content-Length: 16
Origin: http://192.168.1.178
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
Content-Type: text/plain
Accept: /
Referer: http://192.168.1.178/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8

THIS iS the FILE

I was not reading anything after a new line followed by a blank line. After removing that, I get what I need.

Props to ViacheslavMezentsev
Thanks you very much!

Wireshark can help you too. My first link describes how to calculate where the binary data located. Also you can get file name.