Difficulty using WebServer Response() with SD card

Im having difficulty with a small web server project Ive been working on. My main objective is to set up a server on the Cerberus which can serve files from the SD card. Almost everything works well, except for the actual serving. I am using MNMF version 4.2, and updated the firmware from the very latest version (July 23). Heres the program start, just for reference:

public partial class Program
{
    void ProgramStarted()
    {

 //Set methods to handle SD card in/out events...  

        sdCard.SDCardMounted += new SDCard.SDCardMountedEventHandler(sdCard_SDCardMounted);
        sdCard.SDCardUnmounted += new SDCard.SDCardUnmountedEventHandler(sdCard_SDCardUnmounted);


 //Start the network...

        string ip = "";
        Debug.Print("Network Startup");

        Microsoft.SPOT.Net.NetworkInformation.NetworkInterface[] ethintf = Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
        foreach (Microsoft.SPOT.Net.NetworkInformation.NetworkInterface nif in ethintf)
        {
            Debug.Print("Intf: " + nif.IPAddress);
            ip = nif.IPAddress;
        }

        if (ip == "")
        {
            Debug.Print("ERROR: No ethernet found!");  //TODO: Recover and retry
            return;
        }

 //Then network is up, now set up the handler for web events and wait fore the fish to bite...

        WebEvent webEventProcess = WebServer.SetupWebEvent( "index.html" ); 
        
        webEventProcess.WebEventReceived += new WebEvent.ReceivedWebEventHandler( webEventProcess_WebEventReceived);

        WebServer.StartLocalServer(ip, 80);

    }

So far so good. SD card detection works well, and I can dump out the available files from the ‘mounted handler (which kicks off on program start and also mount the card). The networking seems very solid. My issue is in the web handler below. Specifically, when I use Respond() to try to serve the file, I get error messages, despite the fact that the file does get sent.

void webEventProcess_WebEventReceived( string path, WebServer.HttpMethod http, Responder responder )
{

ContentType = “text/plain”;

   GT.StorageDevice fileReference = sdCard.GetStorageDevice();

   if (System.IO.File.Exists("\\SD\\" + path))
        {
       Debug.Print( "yep, we can find it...");
            try
            {
                responder.Respond( System.IO.File.ReadAllBytes( "\\SD\\"+ path ), ContentType);

                System.Threading.Thread.Sleep(1000);
                Debug.Print("File served...");
            }
            catch (Exception e)
            {
            Debug.Print("Exception while sending file"); 
            throw e;
            }
        }

}

I think the issue is related to the use of ReadAllBytes() as a parameter, which should open the file, read the contents (into some secret place) and then close it again. This seems like it should work, but I get the following massage in Debug:

Failed allocation for 441 blocks, 5292 bytes

The program limps along, and tries to serve a second file. This time Debug reports:

Failed allocation for 198 blocks, 2376 bytes

Failed allocation for 172 blocks, 2064 bytes

A first chance exception of type ‘System.IO.IOException’ occurred in Microsoft.SPOT.IO.dll
Exception while sending file
A first chance exception of type ‘System.IO.IOException’ occurred in NetServe.exe
Error invoking method “Gadgeteer.Networking.WebEvent” (check arguments to Program.BeginInvoke are correct)

At this point program execution recedes deep into the jungle, and must be restarted. I have re-updated the boot loader and NMF 4.2 SDK files a couple of time just to be sure all is well.

Its likely that ReadAllBytes() is setting up some buffer somewhere, and doesnt have enough space for the whole thing. Id like to send the file in chunks of 5K bytes, but havent found a good way to do it within the context of Gadgeteer.Networking.

Any suggestions?

Using code tags will make your post more readable. This can be done in two ways:[ol]
Click the “101010” icon and paste your code between the

 tags or...
Select the code within your post and click the "101010" icon.[/ol]
(Generated by QuickReply)

Welcome to the forum.

This is how you read a file from the SDCard and serve it:


      using (FileStream fs = new FileStream(@ "\SD\index.htm", FileMode.Open, FileAccess.Read))
            {
                byte[] buf = new byte[fs.Length];
                fs.Read(buf, 0, buf.Length);
                responder.Respond(buf, "text/html");
            }


Thanks for the fast response, JayJay. Your suggestion looked good and I was optimistic as I cleaned up my code and pressed the key to start the debugger. Unfortunately, I have the same results. Here’s the output from the debugger:


 >>text/html<<
 ++\SD\index.html++

Failed allocation for 172 blocks, 2064 bytes

A first chance exception of type 'System.IO.IOException' occurred in Microsoft.SPOT.IO.dll
Error invoking method "Gadgeteer.Networking.WebEvent" (check arguments to Program.BeginInvoke are correct)


And here’s the code as it stands at the moment:

        void webEventProcess_WebEventReceived( string filename, WebServer.HttpMethod http, Responder responder )
        {
            string ContentType = "text/html";
            string path = "\\SD\\" + filename;

            Debug.Print( "looking for " + path + "..." );

             Debug.Print("\n >>" + ContentType + "<<");
            Debug.Print(" ++" + path + "++\n");

            using (FileStream fs = new FileStream( path, FileMode.Open, FileAccess.Read))
            {
                byte[] buf = new byte[fs.Length];
                fs.Read(buf, 0, buf.Length);
                responder.Respond(buf, ContentType );
            } 

In addition, since the entire file is being read into ‘buf’ and memory space on the Cerberus is limited, the server is limited in the size of the file it can serve. I want to break the file into to pieces and serve it up bite by bite, say in 5Kb chunks. I can’t see how to do that with the Gadgeteer.WebServer objects, and am thinking of using an approach based on System.Http instead. This will be more work, but I’ll have the flexibility I need.

Any thoughts?