Getting occasional "404: File Not Found" in WebHTMLViewer

I am using an HMTLViewer inside my WebPage. And something, when I use HTMLViewer1.LoadPage (htmlText), the viewer shows:

[quote]404: File Not Found

The requested URL “/110FF6AA6823CD665F9B5166B15BF9C99BF216B3/files/6037-8068-1074-1164-2830/source.html” could not be found. Please check your request and try again.

Remote Address: 127.0.0.1[/quote]

When I reload it once more, it usually goes away and shows the assigned html rendering as expected.

Happens in both RS 2012r2 and 2019r1.

What’s up with that, and how can I prevent it?

Are you creating the file just before you view it? If so, it might not be ready yet, the OS/virus checker might be doing something with it after your close.

It’s not a file, it’s a string.

Underneath the framework writes it to a file.

I’m confused, are you talking about HTMLViewer or WebHTMLViewer?

[quote=437117:@Thomas Tempelmann]I am using an HMTLViewer inside my WebPage. And something, when I use HTMLViewer1.LoadPage (htmlText), the viewer shows:

When I reload it once more, it usually goes away and shows the assigned html rendering as expected.

Happens in both RS 2012r2 and 2019r1.

What’s up with that, and how can I prevent it?[/quote]
Make sure the WebFile isn’t going out of scope. It must exist long enough for the browser to request it.

Yes, I meant WebHTMLViewer

And no, there is no WebFile. I already explained that I just pass a string to LoadPage. THERE IS NO FILE on my end.

But if everyone thinks it’s a problem with the file, and me no having control over any file, it must be the WebHTMLViewer’s fault, right? I.e. a bug?

Might be a timing issue, which it seems to me is perhaps a possible inherent problem with HTMLViewer and WebHTMLViewer (I’ve never used the latter). If the method containing:

HTMLViewer1.LoadPage (htmlText)

exits before the Viewer has a chance to load the temporary file containing htmlText, then by the time the Viewer gets around to reading it, the file has disappeared.

Tried putting a delay after the LoadPage? Something like:

HTMLViewer1.LoadPage (htmlText) app.SleepCurrentThread (20)

It’s to do with the way macOS writes files asynchronously. I usually see it when people are doing a bunch of manipulation in one function in the Desktop framework. Xojo doesn’t stop and wait for the file to be completely written. I’m not sure if there’s a workaround, especially since this is framework level.

Though, you might be able to get away with a WebSDK control to take the HTML straight to the browser… again. Google suggests that you can display HTML without a file in an iframe

Relying on SleepCurrentThread is discouraged because you can’t guarantee that the write will be done.

Bug then in that case.

Tim, by framework you mean Xojo’s right? Not the OS framework (I have this effect on both macOS and Linux, BTW.)

Do you know for sure that Xojo’s LoadPage writes a file internally? Probably generating a WebFile?

However, I don’t by the async argument because if it’s Xojo, there is no async for writing a file, i.e. I don’t believe Xojo’s framework would write a file in a bg thread and then continue on the main thread. That’d be (a) too advanced and (b) quite pointless. And once a file write is done, the file gets closed, and that’s it. There is no spotlight on Linux that would then grab the file and keep it open. And even if it did, that should not prevent the html renderer from reading the file, too.

I rather wonder, assuming it’s a WebFile, like Thom suggests, that the LoadPage code does not hold on to it long enough, and that might then delete the file again? Only Thom could answer that, though, as that’s part of the compiled Xojo framework code running on the server, and not part of the js code that we could have a look at, I am afraid.

The 404 error is definitely evidence that Xojo is using a webfile to feed the WebHTMLViewer.

The path to the missing file is in the error report:
“/110FF6AA6823CD665F9B5166B15BF9C99BF216B3/files/6037-8068-1074-1164-2830/source.html”

To me, that sounds like a bug. But the random nature of the 404 error will make it difficult to reproduce.

I actually never noticed it, and I generally manipulate rather complex pages.

The only workaround I see would be to create your own webfile.

http://documentation.xojo.com/api/web/webfile.html#webfile-data

Make sure to make it a property of the webpage, so it does not go out of scope.

@Michel Bujardet I’ll give it a try and report back.

… Actually, I just tried to use a WebFile - but I can’t figure out how to get that into the WebHTMLViewer then.

WebHTMLViewer does not appear to have a function that lets me pass a WebFile for rendering. How is this supposed to work?

[quote=437209:@Thomas Tempelmann]@Michel Bujardet I’ll give it a try and report back.

… Actually, I just tried to use a WebFile - but I can’t figure out how to get that into the WebHTMLViewer then.

WebHTMLViewer does not appear to have a function that lets me pass a WebFile for rendering. How is this supposed to work?[/quote]
Pass the url of the webfile.

You mean this, probably:

htmlView.URL = htmlFile.URL

That seems to work, but now, when I do the same thing again, I get a file error 104 (FileInUse). And I have no idea how to “unuse” the file. There is no close on WebFile or something similar. It appears that WebFile holds the file open (why?!?) after I load it with its Open() function, and there’s no way to release it again.

This behavior is very confusing to me.

Here’s the complete code I’m using:

dim html as String = self.createHtml() #if false // Sometimes leads to a 404 error, even in Xojo 2019r1: htmlView.LoadPage (html) #else mHtmlFile = nil // attempt to close the the previously created WebFile dim f as FolderItem = SpecialFolder.Temporary f = f.Child("html-" + self.ControlID + ".html") BinaryStream.Create(f).Write html // -> error 104 the second time this gets called dim htmlFile as new WebFile htmlFile.Session = Session call htmlFile.Open (f) htmlView.URL = htmlFile.URL mHtmlFile = htmlFile // retain the web file as per Greg O'Lone's suggestion #endif

Oh, I found that I could assign the html to the WebFile through its Data property instead of loading it from a file. That takes care of the spurious 104 error:

mHtmlFile = nil dim htmlFile as new WebFile htmlFile.Session = Session htmlFile.Data = html htmlFile.ForceDownload = false htmlView.URL = htmlFile.URL mHtmlFile = htmlFile

However:

Now it does not display the file’s html content any more in the HTMLViewer but instead DOWNLOADS it!

Jeez.

[quote=437214:@Thomas Tempelmann]Oh, I found that I could assign the html to the WebFile through its Data property instead of loading it from a file. That takes care of the spurious 104 error:

mHtmlFile = nil dim htmlFile as new WebFile htmlFile.Session = Session htmlFile.Data = html htmlFile.ForceDownload = false htmlView.URL = htmlFile.URL mHtmlFile = htmlFile

However:

Now it does not display the file’s html content any more in the HTMLViewer but instead DOWNLOADS it!

Jeez.[/quote]
The reason in this case is that you aren’t setting the mime type to “text/html”. The default is something that the browser would otherwise download.

[quote=437213:@Thomas Tempelmann]You mean this, probably:

htmlView.URL = htmlFile.URL

That seems to work, but now, when I do the same thing again, I get a file error 104 (FileInUse). And I have no idea how to “unuse” the file. There is no close on WebFile or something similar. It appears that WebFile holds the file open (why?!?) after I load it with its Open() function, and there’s no way to release it again.

This behavior is very confusing to me.

Here’s the complete code I’m using:

dim html as String = self.createHtml() #if false // Sometimes leads to a 404 error, even in Xojo 2019r1: htmlView.LoadPage (html) #else mHtmlFile = nil // attempt to close the the previously created WebFile dim f as FolderItem = SpecialFolder.Temporary f = f.Child("html-" + self.ControlID + ".html") BinaryStream.Create(f).Write html // -> error 104 the second time this gets called dim htmlFile as new WebFile htmlFile.Session = Session call htmlFile.Open (f) htmlView.URL = htmlFile.URL mHtmlFile = htmlFile // retain the web file as per Greg O'Lone's suggestion #endif[/quote]
You’re close here, but you should either not be trying to use the same file on disk each time or just not creating the file over and over.

Still, why does it behave like that?

  1. Why does it keep the loaded file open? To prevent other processes from modifying it? Or is that an oversight (bug) in the framework code?
  2. Why is there no way to release (close) the file again, and why doesn’t it close it once I release the WebFile? There should be no more handle on it, so it should close it. Or isn’t it the WebFile that keeps it open but the HTMLViewer? Then there should be a way to tell THAT to release the file, shouldn’t it?

[quote=437219:@Thomas Tempelmann]

  1. Why does it keep the loaded file open? To prevent other processes from modifying it? Or is that an oversight (bug) in the framework code?[/quote]
    Remember that everything in a web app is asynchronous. If the file wasn’t locked, a browser that was sent a url “a while ago” could end up getting a completely different file than the one you intended.