miguelgrinberg/microdot

second call of send_file method does not serve complete file.

JohannesMaierhofer opened this issue · 7 comments

Hello, I try to serve a super simple html and css file. css file is not sent correctly. It seems that it is the second call of the send_file method that does not work correctly. No difference between sync or async version. Also the content of the files do not matter. First file is always sent fine, second file shows cryptic characters.

I'm using the esp32 Arduino Nano board, MicroPython v1.20.0-445-g8bd2494c9 on 2023-09-04; Arduino Nano ESP32 with ESP32S3.

from microdot_asyncio import Microdot, send_file

app = Microdot()

@app.route('/')
async def index(request):
    return send_file('static/index.html')

@app.route('/index.css')
async def index_css(request):
    print('request css file')
    return send_file('static/index.css')

Please test this example: https://github.com/miguelgrinberg/microdot/blob/main/examples/static/static_async.py. Note that you will need to copy the static/index.html and static/logo.png files to your device.

Let me know if this works well.

Your example works well.

integrating the .png picture in my html code also works well. Just the .css file does not work.

Okay, so then add the css to my example project, then send me all the files so that I can reproduce the problem here.

Alright, here is the most minimal code that shows the issue.

main.py:

import network,socket

SSID ='uPythonWifi'   # Network SSID
KEY  ='1234567890'  # Network key (must be 10 chars)

# Init wlan module and connect to network
wlan = network.WLAN(network.AP_IF)
wlan.ifconfig(('192.168.4.1', '255.255.255.0', '0.0.0.0', '8.8.8.8')) #ip, subnet, gateway, dns
wlan.config(essid=SSID, key=KEY)#, security=4, channel=2, max_clients=5)
wlan.active(True)

print("AP mode started. SSID: {} IP: {}".format(SSID, wlan.ifconfig()[0]))
print("AP ifconfig: ",wlan.ifconfig())
print("MAC Adresse: ", wlan.config('mac'))     # get the interface's MAC address


from microdot_asyncio import Microdot, send_file
app = Microdot()

@app.route('/')
async def index(request):
    return send_file('static/index.html')

@app.route('/static/<path:path>')
async def static(request, path):
    if '..' in path:
        # directory traversal is not allowed
        return 'Not found', 404
    return send_file('static/' + path)

app.run(debug=True)

index.html:

<!doctype html>
<html>
  <head>
    <title>Static File Serving Demo</title>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="static/index.css">
  </head>
  <body>
    <h1>Static File Serving Demo</h1>
    <img src="static/logo.png" alt="logo">
    <p>
    This is a random text that does not say anything useful.
  </p>
  </body>
</html>

index.css:

p {
  font-family: Arial, Helvetica, sans-serif;
  color: #333333;
}

h1 {
  font-family: Arial, Helvetica, sans-serif;
  color: #3070b3;
  text-align: center;
}

The console output of my safari shows . ���%W#.. ���%WINDEX CSS ���%W��%W$�Aindex�3.html����INDEX ~ 1 HTM ��%W��%W%^�LO for the .css file. So it is obviously not correct transmitted. The logo.png works without any issue.

Thanks. Unfortunately I cannot reproduce the problem. Any chance the file system in your microcontroller is corrupted? I would suggest you erase the flash memory completely and then reinstall MicroPython.

Another thing you can try is to modify the static route in the above example as follows:

@app.route('/static/<path:path>')
async def static(request, path):
    if '..' in path:
        # directory traversal is not allowed
        return 'Not found', 404
    if path == 'index.css':
        with open('static/index.css', 'r') as f:
            print(f.read())
    return send_file('static/' + path)

This will print the contents of index.css to the terminal. If this shows garbage, then it would confirm that there is file corruption in your device.

Thanks, this helped to identify that there is a file corruption in the device. It matters in which order I do the upload to the ESP32 via Thonny. Now, it is working!