Your new topic does not fit any of the above??? Check first. Then post here. Thanks.

Moderator: igrr

User avatar
By Vinylon
#39970 You're right, it was an issue with the mobile browser.

This is really odd, but if anybody runs into the same issue, it looks like Android deviates a bit from the http spec and requires attachment filenames to be enclosed in double quotes. So to send a file called 'book.mobi', I needed the following header:

Code: Select allString contentHeader = "Content-Disposition: attachment; filename=\"book.mobi\"\r\n"


And adding a short delay(5) solved the crashing issue, which I guess must have been an overflowing buffer, and I also added a loop to ensure that the client stays connected. So I wound up with this, which seems to work pretty well on both my laptop and phone:

Code: Select allvoid sendRawFile(String fn, File file) {
  Serial.print("Available memory: ");
  Serial.println(system_get_free_heap_size());
  int fSize = file.fileSize();
  String response = "HTTP/1.1 200 OK\r\n";
  // Test with .mobi ebooks, but application/octet-stream would probably work fine.
  response += "Content-Type: application/x-mobipocket-ebook\r\n";
  response += "Content-Disposition: attachment; filename=\"" + fn + "\"\r\n";
  response += "Connection: keep-alive\r\n";
  response += "Access-Control-Allow-Origin: *\r\n";
  response += "Content-Length: ";
  response += fSize;
  response += "\r\n";
  response += "\r\n";
  server.client().setNoDelay(true);
  server.client().write(response.c_str(), response.length());
  Serial.println(response);

  // Stream the file since these chips have very little memory.
  int maxWaitTicks = 50;
  int ticksWaited = 0;
  int readResult = 0;
  int fChunk = 512;
  int progress = 0;
  char responseBlob[fChunk];
  // In case the file doesn't get re-opened before being dl'd again,
  // reset the position after it's read.
  FatPos_t fileStart;
  file.getpos(&fileStart);

  while (progress < fSize) {
    readResult = file.read(responseBlob, fChunk);
    server.client().write(responseBlob, fChunk);
    progress += fChunk;
    // For debugging - will slow DL speed.
    /*if (progress % 16384 == 0) {
      Serial.println(progress);
      if (server.client().connected()) {
        Serial.println("client connected.");
      }
    }*/
    delay(5);
    while (!server.client().connected()) {
      delay(5);
      ticksWaited++;
      if (ticksWaited >= maxWaitTicks) {
        // We're probably not going to reconnect after this long.
        // Reset the file position and return.
        Serial.println("Timeout...");
        file.setpos(&fileStart);
        return;
      }
    }
    ticksWaited = 0;
  }

  file.setpos(&fileStart);
}


At 25-30 KB/s (15-20 if you print to the serial monitor) it's pretty slow, and I get the occasional timeout, but it's a good start. Bumping up the size of the file chunks might help speed it up. Thanks for the help!