Go Down

Topic: [Ethernet + SD] Download zip files from SD (Read 3410 times) previous topic - next topic

bl0w

I'm making a website with ethernet shield.

I wanted to click a link, and download a file from the memory card. Example: zip file

Click a link and do a task I know, I just wanted the part of the SD.

Anybody can help me?

bl0w

and files *.txt, its possible?


:smiley-roll-sweat: sorry for double post.

PaulS

Quote
I'm making a website with ethernet shield.

That's possible.

Quote
I wanted to click a link

Your web page, provided by the Arduino, needs to contain links. Does it? What does the Arduino do when a link is selected?

Quote
Example: zip file

What is the browser going to do with a zip file?

Quote
Click a link and do a task I know,

You haven't demonstrated this.

Quote
I just wanted the part of the SD.

The SD library comes with examples for listing the files on an SD card, and for reading from an SD card. Combining the relevant example with the web server code should be trivial. Read from a file and write to the client. Nothing really to it.

bl0w

#3
Jul 01, 2012, 11:42 pm Last Edit: Jul 01, 2012, 11:56 pm by bl0w Reason: 1
What is the browser going to do with a zip file?


The browser download the file to PC

You haven't demonstrated this.


The code:
Code: [Select]
EthernetClient client = server.available();
 if (client) {
   Serial1.println(F("new client"));
   // an http request ends with a blank line
   boolean currentLineIsBlank = true;
   String vars;

   int varDL=0;
   int dlaio=0;

   while (client.connected()) {
     if (client.available()) {
       char c = client.read();
       Serial1.write(c);
       vars.concat(c);

       if (vars.endsWith("=Download"))
       {
         varDL=1;
       }
       else if (vars.endsWith("/download/arduinoIO"))
       {
         varDL=1;
         dlaio=1;
       }

if (c == '\n' && currentLineIsBlank) {
          client.println(F("HTTP/1.1 200 OK"));
          client.println(F("Content-Type: text/html"));
          client.println(F("Connnection: close"));
          client.println();
          client.println(F("<!DOCTYPE HTML>"));
          client.println(F("<html>"));
          client.println(F("<head>"));
          // meta tag -> Faz refresh ao browser de 2 em 2 segundos
          client.println(F("<meta http-equiv=\"refresh\" content=\"2\">"));

(...)

if (varDL==1) // DOWNLOAD CENTER
         {
           client.println(F("<h1>Downloads</h1>"));
           client.println(F("<a href='/download/arduinoIO'>Matlab Support Package for Arduino (Arduino IO)</a>"));
         }
if (dlaio==1) // DOWNLOAD ARDUINO IO
         {
          //CODE FOR DOWNLOAD FILE
         }

(...)



The SD library comes with examples for listing the files on an SD card, and for reading from an SD card. Combining the relevant example with the web server code should be trivial. Read from a file and write to the client. Nothing really to it.

But the library only read/write txt files.

PaulS

Quote
But the library only read/write txt files.

The examples only show how to read/write text files, since they are the easiest to demonstrate proper functionality.

There is nothing in the library that restricts it from operating on files with other extensions. Whether a file contains "text" or binary data depends on what you write to the file. Text IS binary data, after all.

bl0w

Code: [Select]
if (dlaio==1) // DOWNLOAD ARDUINO IO
         {
          myFile = SD.open("ArduinoIO.zip");
          if (myFile)
          {
            // read from the file until there's nothing else in it:
            while (myFile.available())
            {
              client.write(myFile.read());
            }
            // close the file:
            myFile.close();
          }
          else
          {
            // if the file didn't open, print an error:
            client.println("FILE NOT FIND");
          }
}



i do this: replace Serial.write(myFile.read()); for client.write(myFile.read()); and don't work



to tell the browser that arduino are writing an html page we do:
Code: [Select]
client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: text/html"));


do we have to do a similar thing to another file type? how can I indicate this?


PaulS

Quote
do we have to do a similar thing to another file type?

Yes. The type follows the / (text/html --> text/zip).

Code: [Select]
               client.write(myFile.read());
You should look at the return type from myFile.read() and the expected input to client.write(). You will see that they don't match. An intermediate variable or an explicit cast may be required.

bl0w

if i do this:

Code: [Select]
EthernetClient client = server.available();
  if (client) {
    Serial1.println(F("new client"));
    boolean currentLineIsBlank = true;
    String vars;

    int varDL=0;
    int dlaio=0;
    int html=1;
    int txt=0;
    int zip=0;
    int dltext=0;

if (vars.endsWith("=Download"))
        {
          varDL=1;
          dlaio=0;
          zip=0;
          html=1;
          dltext=0;
          txt=0;
        }
        else if (vars.endsWith("/download/ArduinoIO.zip"))
        {
          varDL=1;
          dlaio=1;
          zip=1;
          html=0;
          txt=0;
        }
        else if (vars.endsWith("/download/sensor.txt"))
        {
          varDL=1;
          dlaio=0;
          dltext=1;
          zip=0;
          html=0;
          txt=1;
        }

if (c == '\n' && currentLineIsBlank) {
          // Cliente terminou de comunicar e o arduino tem de enviar
          // o seguinte cabeƧalho para o browser
          client.println(F("HTTP/1.1 200 OK"));
          if(html==1)
          {
          client.println(F("Content-Type: text/html"));
          }
          if(txt==1)
          {
            client.println(F("Content-Type: text/txt"));
          }
          if(zip==1)
          {
            client.println(F("Content-Type: text/zip"));
          }
          client.println(F("Connnection: close"));
          client.println();
         
          client.println(F("<!DOCTYPE HTML>"));
          client.println(F("<html>"));
          client.println(F("<head>"));
          client.println(F("<meta http-equiv=\"refresh\" content=\"2\">"));

(...)

if (varDL==1) // DOWNLOAD CENTER
          {
            client.println(F("<h1>Downloads</h1>"));
            client.println(F("<a href='/download/ArduinoIO.zip'>Matlab Support Package for Arduino (Arduino IO)</a>"));
            client.println(F("<a href='/download/sensor.txt'>TESTE</a>"));
          }
         
          if (dltext==1) // download sensor.txt
          {
            myFile = SD.open("sensor.txt");
            if (myFile)
            {
              while (myFile.available())
              {
                client.write(myFile.read());
              }
              myFile.close();
            }
            else
            {
              client.println("FILE NOT FIND");
            }
          }
         
          if (dlaio==1) // DOWNLOAD ARDUINO IO
          {
            myFile = SD.open("ArduinoIO.zip");
            if (myFile)
            {
              while (myFile.available())
              {
                client.write(myFile.read());
              }
              myFile.close();
            }
            else
            {
              client.println("FILE NOT FIND");
            }
          }
client.println(F("</body>"));
client.println(F("</html>"));

(...)


The result is this:

FOR ZIP FILE:


FOR TXT FILE:


in the case of. * txt file the true file is this:




I am not able to do that, anyone who knows can tell me?

PaulS

Code: [Select]
                client.write(myFile.read());
myFile.read() returns an int. The data of interest is in the low order byte. You need to research what happens when you call client.write() with an int. It may be sending both the high order byte and the low order byte, which would definitely screw up the file as saved on the PC.

It is not really recommended that you do this. Create an intermediate variable of the correct type to hold the output of the read() method, then call the write() method with that variable.

The Content-Type record should contain application/zip, not text/zip (sorry about that).

You may need to use a "Content-Encoding" record, too.

bl0w

#9
Jul 02, 2012, 07:21 pm Last Edit: Jul 02, 2012, 08:06 pm by bl0w Reason: 1
Maybe this:
Code: [Select]
char myStrings[];
File myFile;

//(...)

if (varDLtxt==1) // download sensor.txt
         {
           int i;
           myFile = SD.open("sensor.txt");
           if (myFile)
           {
             while (myFile.available())
             {
               i=0;
               myStrings[i]=myFile.read();
               i=i+1;
                client.write(myStrings);
             }
             myFile.close();
           }
           else
           {
             client.println("FILE NOT FIND");
           }
         }
//(...)


but we can't declare an array without size, right?


Edit: I test with char myStrings[100];
Now appears the right values on page, but don't download.


TamasM

Hi,

I don't know that the case is still open but I could make the zip download with the following code:

Code: [Select]
              client.println("HTTP/1.1 200 OK");
              client.println("Content-type: application/octet-stream");
              client.println("Content-disposition: attachment; filename=test.zip");
              //client.println("Connection: keep-alive");
              client.println();
                   File sensorFile = SD.open("test.zip");
                  if (sensorFile)
                  {
                    while (sensorFile.available())
                    {
                      client.write(sensorFile.read());
                    }
                    sensorFile.close();
                  }
                  else
                  {
                    client.println("FILE NOT FIND");
                  }
              }

SurferTim

#11
Nov 15, 2013, 01:03 pm Last Edit: Nov 15, 2013, 01:25 pm by SurferTim Reason: 1
@TamasM:  You can greatly increase the speed by using a byte array to store a "packet", then send the array as one send. This is relatively slow compared to the buffered code. Here is the challenge:
Code: [Select]
     while (sensorFile.available())
      {
           client.write(sensorFile.read());
      }

It sends one byte per packet. Every call to client.write() generates a new packet.

Here is my server code running online. It uses a 64 byte array to buffer the data so it sends 64 bytes per packet.
http://68.99.58.119
http://forum.arduino.cc/index.php?topic=197103.0

Here is my code. It uploads about 4 times faster than your current code.
http://playground.arduino.cc/Code/WebServerST

edit: I did not include the ZIP file type in my original server code. I just added it.

Go Up