 Hey everybody, it's Brian. I wanted to drop a quick video note and talk about something near and dear to my heart, uploading from QML. So what am I talking about here? I get asked about a hundred billion times on Facebook, Facebook Messenger thingy, which I largely ignore. You to me, and specifically the folks in the QML for beginners course, they go, hey, I have a QML application. I want to upload a file to a server. There's no built-in QML file.upload. How do you make it happen? And I think I've explained it before, probably explained it pretty poorly. But basically you have to make a C++ class and hook that class into your QML. And as soon as I start saying things like that, it's like you can feel the other person on the other end of the conversation just like die inside because they don't really understand what I'm saying. There's a lot of complexity here, especially when you talk about moving the data in multi-part form via boundaries over to the server using, you know, disposition content. And you've got multi-part mind formats and all this stuff and everybody just kind of mentally checks out. So anyways, wanted to draft up some source code. So it's out in GitHub. It's the void realm slash QML upload. And I'll post a link in the video below. But here's the full code and spoiler alert. We are using the postman-echo.com's posts. So all we're doing is we're saying, can we pump data from the computer or Android device or whatever you have over to a server remotely? If the answer to that is yes, then this video has been satisfied. And I know there's going to be a billion comments down there from people who rush out, grab the code, run it and it doesn't work. And why doesn't it work? We'll talk about that a little bit. So let's go ahead and crack open the code and see what we got. We have a very, very simplistic QML design. It's just have our URL, which you can plug in yours. And then a file. We can choose the file. And then we hit HTTP post and that will push the file out there. Now let's jump into the main here. And this is why I'm not typing because there's a lot of code, but we're going to walk through it. I've got in our main.cpp just some test functions here. So this class does a little bit more than just upload. We can actually do a get. We can do a post. We can post a file. See I'm using .txt. Obviously replace this with whatever file you're using. And we can post a PNG, which would be a file. This is actually pretty neat. Notice how we are setting a raw header. This is one of those little gotchas. So if you grab the code and upload it to your custom PHP application, like that on HostGator or some other post, it might not work because you have to set the user agent. That's one of the little gotchas here. They try to block out spam bots and things like that. So they're actually looking for some specific string. And you can go out to Google and look up HTTP header readers and just it'll tell you what your user agent is. From there, all we're doing is we're saying file upload, post a file, and then we're posting to that postman echo, which is going to push back a JSON string. The path of the file, this guy, replace that with whatever you got. And then you have your content disposition. This would be your actual form data. Like imagine you're looking at a web page and you have different form elements. We're using one called notes and we probably should have changed that to image or something. But that's just the test functions, right? We don't really care about this too much. And I'm going to comment that out and we can comment this out. So if you want to use any of those test functions, just uncomment this file upload and then whichever test function you want. And here we're saying QML register type because, yep, we want to make sure this actually works from QML. That was the whole point of this. So we're just saying register type file upload our C++ class under com company file upload 1.0 under the name file upload. Go ahead and jump over to our QML. Pretty, pretty simple. We just have a pop up here, a file dialogue. And then here is our file upload class. If you're wondering how we got that, it's a combination of this register type in the main function and we have to shockingly import it. And then it's very simple. We're just giving it an ID and we're saying on complete pop up that pop up. Boy, say that four times your files pop up that pop up with a message of the status. Now, if you have no idea of what a status is, pause this video, you're not ready to do this. The reason why I say that what you're doing and you have to have a little respect for what you're doing here is you're taking a file, grabbing those raw bytes and let's just dive into the code here. Cue the like the Super Mario music. There it is. Post file. So what we're doing is we're taking a URL, the remote server, a local path, our device, be it computer, handheld device, phone, whatever, and then whatever disposition we want it out of the form. And maybe that's not even right. I may have to change that in the future. Stripping out that annoying file, file colon whack whack and then just saying if it exists, then we're going to make a mime type, meaning we're going to tell cute. Hey, guess what type of file it is. So you don't have to type in the annoying like text slash HTML. If you have no idea what that is, again, you're probably not ready for this video because you have to actually tell the server. Hey, this is the file type using what's called a mime type or mime encoding. Then from there, we want a queue HTTP multi part and you can put more parts, but we just have the one part. And we're saying we want form data type. And then we're just going to say, OK, we're going to take our part. We're going to say content header and then we're getting the mime type. That would be, you know, what type of file it actually is. I told you this was not simple. And then we're going to say set header content, disposition header. This is the part of the form that it belongs to. And then we're going to say file and notice that's a pointer. So we're going to just crack that file open and read only mode. We're going to set that part to the file, meaning we're going to say this part is going to read the file. Notice how, and this is straight out of the cute documentation. We cannot delete file now. When I say delete file, we're not actually deleting the file off the hard drive. We're deleting that pointer because we're in C++ land. We have to manage our memory. So we have to delete it with a multi part. So we're just setting a parent. Wow, that is confusing. Cute. Please make that super simple. All right. From here, we're saying multi part append the part. Remember, you can have multiple parts. So you could have like dozens of files or whatever you wanted. And then we're just doing a network request. And if you want the simpler versions, it's up here like getting data, posting data. But basically you just saying network request and then you can set any sort of content header you want. Like in our test, we set the header of user agent. That's how you mimic a browser. Flip back here. Anyways, once we have made our request, we're going to say cute network access manager. Go ahead and post. Now the difference between get and post is subtle, but profound. So get, you're actually just pulling the information where post you're saying, here's some information for you. Give me a response back. And that's what if we go into post band echo, you can actually use this right here. You can just post right here or you can do this whole serial and test and play around with it. And it will give back a Jason response like that. So it's pretty good for a diagnostics tool. So you can figure out what the hex actually going on in your code. Anyways, once our request goes off into the queue network access manager land, it just disappears. And we have to actually monitor that through signals and slots. So I am actually connected to the finished SSL and encrypted. So I've got some warnings in here. So for example, if you start getting SSL errors, you're going to have to figure out what exactly you need to do on your end. And I've got some warnings in here with the function information. Same thing with encrypted. The real heart of the code here is in finished. This is where we've actually sent the data over to the server and the server has given some type of response back. And what we're just simply doing is reading the status code. Now, if we get anything other than status 200, there was some sort of problem. I'm sure you've seen like 404 not found or 403 forbidden or 50 something. I forget the error codes. It's been a while, but basically anything other than 200 and you've got some sort of problem you're going to have to look at. And that's why I say if the code's not 200, it looks like you have some troubleshooting to do. And this is what I mean by this solution will probably not be a one size fits all meaning don't expect to download this. And it just magically solves all your problems. Probably at this point going to have to go back into your server. And especially if you're renting a server from like a host gator or any of the other, you know, kind of third party providers, you're going to have to ask them, hey, what do I need to do to get this through? And that's why in our tests here, I put this how to imitate a user agent because that was the big hurdle I had right off the bat is I didn't have a user agent. So therefore it just blocked the request like my PHP script didn't even see it. It just never happened. And it was so annoying because I sat here for like 100,000 years trying to figure it out. Once I plopped a user agent in there, it just fired right through into my PHP script. Then I ran into another problem. The provider had file uploads blocked. How? I don't know. I'm not a PHP guru. I had to call them and say, hey, unblock that. Then I had another problem. I needed to set the permissions on the folder where I wanted to dump the file in the server and all that. So really what I'm getting at is this application becomes a very small part of a very large architecture that you have to kind of troubleshoot. So disclaimer, don't expect this to just magically work. And that is why we are using the postman echo because if you can get the information out of the application onto a different server, voila, the application part is pretty much done. You may have to tweak a few things like the disposition content. Anyways, enough talking. Let's see this thing in action. We got our QML. And we're going to say when we click that HTTP post button, the uploader is going to post the TXT URL and the TXT file, meaning the remote host, the local file under the name notes, and it's just going to actually upload it. And you'll see that in this application down here. So let's save run. And this VM gets a little bit boggy when I try to do QML for some reason. So I'm going to simply choose a file. Yeah, see it's holding up a little bit. I got to put my memory on this thing. All right. So we're going to go to code, go to Q. And I'm just going to select this PNG here, hit open. Notice how it's got this file, whack, whack. We're stripping that out up here. And I'm going to hit post and you'll see all the magic happen here. Status 200. So we have successfully uploaded that file. I'm going to hit close. And you can see the content length from the response was that the content type was multi-part form data. It was the boundary in case you really wanted to know what the boundary was. And then the mind versions, the accepting coatings. I mean, you can see this gets really, really complex, really fast. So if you don't know anything about the HTTP protocol, you're probably very, very lost. And all of this gobbledygook, this is the raw hex encoded bytes out of the actual file. And you can see it was a PNG file right there. So, and it was under the form notes. So this thing should work for the most part, but you're probably going to have to tweak it for your specific use case. Unfortunately, I'm not going to be able to deep dive into your server code or help you figure out why your Android permissions aren't set correctly or anything like that. I just get a lot of requests for how do I upload a file from QML to some other provider somewhere. And unfortunately, that other provider somewhere is where most of your problems are really going to happen.