Starting in 2020r1, in the HandleURL event, there is a new response argument (WebResponse class). It has a file property to return a file. Previously, this had to be done using the request.file.
In 2021r1 and 2021r1.1, response.File does not work anymore. Using response.file returns a generic 404 page (I assume provided by the Xojo framework). You have to revert using request.file which, strangely, works.
Try the following to serve png files on your desktop. In the App.HandleURL event:
I don’t think it’s an old bug that never got corrected. Before 2020r1, you would send a file using “request.file = myfile” and it worked. When 2020r1 was released, there was a new WebResponse class to separate the request from the response, which makes a lot of sense. HandleURL now has both a request and response parameters. It’s more logical to say “response.file = myfile” to send a file as part of the response. I converted our api backend to the new framework and compiled it with 2020r1 and it worked. So no bug at that time.
Fast forward to now, facing the memory leaks and temporary file buildups, I was excited to recompile with 2021r1.1. It did fix both problems but then sending files suddenly stopped working. Which led to my investigation … and findings My workaround was to go back to using “request.file = myfile” which, strangely, works perfectly in 2021r1.1.
I do not have 2020r1 installed and I did not test with every release after that to find the exact one where the problem first appeared. But I would rather call it a recently introduced bug, not an old unfixed one.
Anyways, if anyone has experienced this, please chime in!
So working through your code I think I see what the problem is…
First of all, you are passing a path to Folderitem.Child where it only takes a Name. Passing a path which contains a / character changes the path to a filename and the file ends up being Nil.
I’ve modified your code to support paths:
If Request.Path.Right(4) <> ".png" Then Return False
Dim f As FolderItem = SpecialFolder.Desktop
Dim pathParts() As String = Request.Path.Split("/")
Try
For i As Integer = 0 To UBound(pathparts)
f = f.Child(pathParts(i))
Next i
Catch ex As NilObjectException
Return False
End Try
response.File = f
response.Status = 200
response.MIMEType = "image/png"
Return True
Exception e
Return False
Hi Greg. Thanks for looking into this, I really appreciate it. You’re right that if I pass a full path in the URL, the folderitem is invalid.
However, I’m not passing a full path, I only put the filename in the URL. This was a simple test that only supported files directly on the desktop. The URL I used was http://127.0.0.1:8080/myfile.png
I have checked the actual folderitem in debug to make sure it was pointing to a valid file.
For good measure, I tried hardcoding the filename and returning a different response (not found) if any exception is raised with a status code of 200. This way, the app should never return a 404 even if an exception is raised.
Running this has the same result: receiving a 404 page.
I added the UnhandledException event to the app, and there is in fact an unhandled exception raised. That’s where the 404 page comes from, not from the code itself in HandleURL. Here’s the stack:
Good points, Dirk, thanks for taking some time to help.
Did you try it without the Content-Disposition header ?
Yes. I just tried again to be sure. This only makes the browser (most of the time) save the file instead of displaying it.
Are you 100% sure xojo/your app has access to the desktop ?
Yes. Also, in the first code I posted I built the folderitem and assigned it to a variable and then checked its content in debug to see if it was valid and existed. It did.
Remember the exact same code works in 2020.
I’d be curious to see any example of code in HandleURL using response=file that runs successfully in 2021. Has anyone tried?
Using the sample code results in getting nothing for me too. If I make the suggested change, which is shared below, the file is returned via the browser as expected.
Response.File = SpecialFolder.Desktop.Child(Request.Path) should work but does not. Request.File = SpecialFolder.Desktop.Child(Request.Path) works but should not.
Thanks Greg. I’ll definitely use MimeType, it’s cleaner.
I created a new empty web project and I tried your code and it doesn’t work. Now I’m really baffled
Maybe there’s something in my environment? I’m on MacOS 11.2.3, MacBook Pro 2019 Intel. No plugins other that the default Xojo ones. Anything else you think I should be looking for?
I tried your sample code and it does not work for me with a clean install of Xojo 2021r1.1 on macOS 11.3.1. If I replace response with request for the file, which I’ve shared below, it works.
If Request.Path.Right(4) <> ".png" Then Return False
Dim f As FolderItem = SpecialFolder.Desktop
Dim pathParts() As String = Request.Path.Split("/")
Try
For i As Integer = 0 To UBound(pathparts)
f = f.Child(pathParts(i))
Next i
Catch ex As NilObjectException
Return False
End Try
request.File = f
response.Status = 200
response.MIMEType = "image/png"
Return True
Exception e
Return False
Any idea why response is failing for Bruno and I but not you? MD5 is 141ebb4849fc952710c3eec76baae262 for /Applications/Xojo 2021 Release 1.1/Xojo.app/Contents/MacOS/Xojo on my system.
@Greg_O_Lone It should also be noted that Bruno and I are both running Big Sur. We’re running different versions of Big Sur but are both on macOS 11.x. I’m on 11.3.1 and Bruno is on 11.2.3. If the three of us are all using the same Xojo binary and are all on Big Sur, the differences in behavior will be be even more puzzling.
Additional info: my final project runs on 3 different Mac Minis, two are on MacOS 10.15.7 and one is on 10.13.6. All 3 showed the same problem with response.file and for all 3, changing response to request fixed it. They all use a compiled app.