 Hey everybody, it's Brian and welcome to the 64th Qt tutorial with C++ and GUI programming. Today we're going to be actually downloading some stuff off the web using Qt. We're going to cover the QHTTP class. So just go into the help system type QHTTP and just browse over this class real quick. If you're wondering what HTTP stands for, it's Hypertext Transfer Protocol. That's how files are moved around the web. For example, if you go to a web page, here's my website. You notice the HTTP in front of this. It means we're using the Hypertext Transfer Protocol. Part of this protocol is you make a request using Git. And when I say using Git, you're actually sending a packet saying, get this file. The web server will turn around, see if the file exists. If it does, it sends back the file. In this case, looking at this, it sent back the web page. You can see there's the contents of the web page that we downloaded. And it downloads all the images and stuff too. And if it doesn't exist, it sends back an error code. Like we'll just say index.html. And you see how it says the dreaded 404 not found. Well, 404 is a status code. That's an HTTP status code. So what we're going to actually do today is we're going to make a program to download files. So we're going to say new. And we're just going to say project console application. I'm going to call it do HTTP. And eat test. Next, next, finish, finish. And we've got our real basic application here. Now, the first thing you want to do is actually add a reference into the network module. Whoops, help if I could spell network. And once you've added a reference to the network module, it'll rescan your project. And then life goes on. You can do what you need to do. So we will add a new class. And we'll just call this downloader. My computer's been acting. Sorry, you want to inherit Q object while I'm thinking about it. My computer's been acting a little funky here. I installed Windows 7 SP1 and I've been having all sorts of weird issues. Like it blue screened on me 20 minutes ago. And it hasn't done that in about 10 years. So kind of concern that maybe Microsoft didn't get their stuff right this time. All right. Now we want to include Q HTTP. We also want to include Q file. And let's of course include Q debug. Help if I got the pound sign in there instead of the three. Now that we've got those in there, we need to make a function that we're going to actually kick this whole process off. So we'll say void, do download. And of course we need the object we're actually going to work with here. So we'll say Q HTTP. And we'll just call it HTTP. That way we know what it is. And part of working with the Q HTTP class is it will, while it's downloading, fire off some signals here. Here's the signals we got to work with. You know, there's a whole bunch of them. And I'm not going to get into all of them. But the ones we're really focused on are state changed, response header received, and request finished. And what these are is the state changed. Let's just click on that. There's different states of the connection. Unconnected, host looked up, connecting, sending, receiving. If you watch the network primer that I did last night, you'll really understand what I'm talking about. This uses a TCP connection. So it's got that underlying three-way handshake. And the state change signal tells you where in that handshake you are and what the class is actually doing under the hood. The response header received is part of the HTTP protocol. When you request a file, it sends you the file. But in front of it, it sends a header that has metadata about the file and the transaction that you're making. So the first packet always has this header. So that's when you get the header. And request finished is when the actual request is finished and you have all of the file. I'm not 100% certain, but I'm sure some of you gurus out there are going to correct me if I'm wrong. I believe the QHTP class caches it into a temp file somewhere, and then you can pull it out wherever you want. So without further ado, let's actually flip back here and implement these. So we're just going to copy that, paste it, and then we want the response header received. Copy that, and then we want ready read. Sorry, not ready read. We want request finished. You might be asking yourself, what's the difference between ready read and request finished? Well, ready read is fired whenever you have data in the buffer that can be read. Request finish is fired when the entire process is done. So if you try doing this off of ready read, you may not have all of the file. You may only have a chunk of it. You have a certain window which you can send packets in. So if you have exceeded that window, let's just think of it as a bucket. Let's say you've got a one gallon bucket and you're trying to transfer five gallons of water. What's going to take five buckets or five packets to get this through? Now I don't want to scare you with the details. You don't really need to know any of that to use this class. You just need to understand the concept of how that works. So now that we've got our function prototypes here, let's go in here and actually implement these. We'll say void, downloader, do download. And that is going to actually be where we're going to kick this whole process off here. And we're just going to implement these really quickly. All right, first thing we're going to want to do now that we've got them implemented is we're going to want to flesh out these slots. So that way we can see exactly what's going on here. So let's do the state change first. So we'll say switch, state. And I'm just going to do this very quickly. K zero, I say quickly and then I goof up. Okay, K zero, break. And I'm looking at my notes, but you may have to flip back over into here and actually go state changed and state. And that way you can see which state is which value. And zero is unconnected. And there are seven states that we need to worry about here. State one is host lookup. Let's actually uppercase that just because I'm picky. State two is connecting. And really you don't need to worry about the states. I'm just doing this for illustrative purposes just so you can see what's going on under the hood. I really want you to understand that there's a multi-part process. You don't just fire something out in the server returns data. I mean, there's a whole lot that happens in the background here. Five is connect. And six of course is closing. All right, now our response header received. Remember, this is gonna be the first packet. If we're transferring a file that takes five buckets, this will be the first bucket. We're gonna get the response header. Now remember, we don't actually have any real data yet. We're just getting the header or the information about the data we're gonna get. So say Q to bug. And we want the size. So let's just grab size. And let's grab our reference to the Q response header. And we'll say content length. And through the magic of copy and paste, we're gonna add a few more things here. We want the type. Because we wanna know whether we're grabbing, you know, a text file or an image or anything like that. And we wanna know the status code, the HTTP status code. Remember when I went to the webpage and I typed in a file that didn't exist? Well, that's the status code. Just for information purposes, if it says 200, that means the whole thing's okay. It literally means 200, okay. Anything in the 400s means there's a problem with your request and 500 means there's a problem with the server. Okay, now we've got our request finished. And notice how there's this boole error. Let's say you tell if there was an error in the whole process. So what you can say is if error, then else. And we'll just do Q debug. When you say error, that way we know something bad happened. Otherwise we'll say Q debug. Okay, that way we know. You know, the request is finished, life is good. Everything goes on here. Now this is fine and dandy, but we haven't actually told it to download anything yet. So what we need to do is actually create our object. So HTTP equal new, Q HTTP. Say this is the parent class. And now we wanna connect up our signals and slots. We got stay changed. And then this with slot. We want the response header received. And finally we will connect the HTTP signal. And what did we have here? We had the request finished. Now that we've got our signals and slots implemented. The final step of this is we need to actually request a file. So we say HTTP set host that way you're setting the server. And you can set it to whatever you want, but I'm just gonna do my server void realms. Just because I'm used to my server and I know how it behaves. And then we want to actually get a file. And we're just gonna get the root of that website or the slash. And what this will do once we go out to the website is it'll say, okay, get the base directory here. And if there's a default file, the web server will serve the default file. You see, there's our slash right here at the end. So what the web server does is says, okay, go to the root of the website, looks for the defaults file, which in my website's case is called default. Hope if I can spell default.aspx. So if you go to slash defaultaspx, it's the same thing. And you should note before we fire off this tariff, if we go index.html, it's gonna return a 404 not found. So let's save our work. And really quickly, let's call out our class here. So we'll say downloader. See down to download, compile and run. And with any luck, we don't have any errors in our code here. And went faster than I could drag it over. But you can see how it says connecting, sending, reading the size. That's the size of the information. The type, the mime type is text slash HTML. It means it's a text file. The status is 200, remember 200 is good. And connect means we're connected. Now you notice how it didn't disconnect. Part of the HTTP protocol is the keep alive parameter. And what that'll do is if there's no problems with your request, it'll just keep that connection open for as long as you need it. That way you can make multiple requests off the same connection. Because making a connection, making that three way TCP handshake is actually rather expensive and slow. So they just keep the connection open so you can just keep making requests off the same connection. Now, let's show you what happens if we request a file that doesn't exist. Remember index.html does not exist off my website. So we'll compile, run. And you see we get different results here. We get connecting, sending, reading 4040 for the size. Type text.html status 404. Remember that's the not found. And then notice closing, unconnected. Meaning the web server just said, goodbye, I'm done with you. So that's really all you need to know about these connections. Now, before I close this tutorial, I know somebody out there is going to ask me, Brian, how do you download this to a file? Well, I'm kind of glad you asked. In the request finish, we could have okay, but we can also just dump this into a file. And I've got a directory out here. There's absolutely nothing in it. And we're going to download it to that directory. So what I'm going to do is say Q file. And we'll say file equal new. Oops, better make this a pointer. And we want to give this a name here. I'm going to throw mine in E test downloads, but you can put it wherever you want. Remember to change your slashes to the universal slash. Otherwise it'll read it as an escape character. And we'll say test.txt. And then we'll say if file.open. And we want the mode, which we're just going to say append. Then we'll delete the file that way. We don't have a memory leak, but if it's open, then we want to actually write that information to the desk. So we're going to say file, write. And we want HTTP, read all. And what that'll do is that'll give us a Q byte array. And we can take that Q byte array and we can just throw it right into the QIO device, the Q file. And that'll write everything out to disk. And then we'll say file. We want to flush the contents of this, make sure everything gets written to disk. And file close. There we go. Now you should also note instead of doing this off the request finish, you can actually hand it in the get as a parameter. You can hand it a QIO device. So you could just make a Q file in memory and put a reference to the Q file pointer right here. That way, as it's getting the information, it automatically writes it off to disk for you. So you don't have to worry about the IO. And then when the request is finished, you would just, you know, of course, flush close and delete your file. But I'm trying to keep this tutorial really simple and very easy to understand. So let's save our work, compile and run. And you can see how it's 404 error, you know, file not found, closing, unconnected. But if we go out to our download directory, you see we now have this test.txt. And if we open this up, you see there's the contents. And this is the actual information that's displayed on the webpage. You can see it actually says, you know, HTTP 404. And it says, you know, the page cannot be found. So that's what this is right here. And you can actually prove that by going, you know, right click, view source. And that's what we just downloaded right there. So anyways, I need to cut this tutorial off because I'm running out of time and, well, you know how it is with YouTube. So thank you for watching. I hope you found this video educational and entertaining. And please, you know, shoot me any questions you guys got. I enjoy your feedback. It really keeps me on my toes and, you know, keeps me honest because sometimes I say things and think I know what I'm talking about and I really don't. So just definitely keep up on that feedback.