Since we don't have any files in our FTP directory yet (except the file list), let's write the code to allow us to upload our first file.
- First, open mainwindow.ui and right click on the Open button. Then, select Go to slot and select the clicked() option:
![](Images/9101a98a-64cd-4902-b2ea-d463509b03d9.png)
- A slot function will be automatically created for you. Then, add the following code to the function to open up the file selector window for our users to select their desired file for upload:
void MainWindow::on_openButton_clicked() { QString fileName = QFileDialog::getOpenFileName(this, "Select
File", qApp->applicationDirPath()); ui->uploadFileInput->setText(fileName); }
- After that, repeat this step and do the same for the Upload button. This time, the code for its slot function looks something like the following:
void MainWindow::on_uploadButton_clicked() { QFile* file = new QFile(ui->uploadFileInput->text()); QFileInfo fileInfo(*file); uploadFileName = fileInfo.fileName(); QUrl ftpPath; ftpPath.setUrl(ftpAddress + uploadFileName); ftpPath.setUserName(username); ftpPath.setPassword(password); ftpPath.setPort(ftpPort); if (file->open(QIODevice::ReadOnly)) { ui->uploadProgress->setEnabled(true); ui->uploadProgress->setValue(0); QNetworkRequest request; request.setUrl(ftpPath); uploadFileReply = manager->put(request, file); connect(uploadFileReply,
SIGNAL(uploadProgress(qint64,qint64)), this,
SLOT(uploadFileProgress(qint64,qint64))); connect(uploadFileReply, SIGNAL(finished()), this,
SLOT(uploadFileFinished())); } else { QMessageBox::warning(this, "Invalid File", "Failed to open
file for upload."); } }
The code looks a bit long, so let's break it down:
- We used the QFile class for opening the file that we want to upload (the file path is taken from ui->uploadFileInput->text()). If the file doesn't exist, display a message box to inform the user.
- Then, we fill in the information of our FTP server and the upload destination into a QUrl object before feeding it to a QNetworkRequest object.
- After that, we start reading the content of our file and provide it to the QNetworkAccessManager::put() function.
- Since we have no idea when the file will get uploaded completely, we used the SIGNAL and SLOT mechanisms provided by Qt. We linked the uploadProgress() and finished() signals to our two custom slot function called uploadFileProgress() and uploadFileFinised(), respectively.
The slot function uploadFileProgress() will tell us the current progress of our upload, and therefore we can use it to set the progress bar:
void MainWindow::uploadFileProgress(qint64 bytesSent, qint64 bytesTotal) { qint64 percentage = 100 * bytesSent / bytesTotal; ui->uploadProgress->setValue((int) percentage); }
Meanwhile, the uploadFileFinished() function will be triggered when the file has been completely uploaded:
void MainWindow::uploadFileFinished() { if(uploadFileReply->error() != QNetworkReply::NoError) { QMessageBox::warning(this, "Failed", "Failed to upload file: "
+ uploadFileReply->errorString()); } else { QMessageBox::information(this, "Success", "File successfully
uploaded."); } }
We are not done with the preceding function yet. Since a new file has been added to the FTP server, we must update the existing file list and replace the files.txt file stored within the FTP directory. Since the code is slightly longer, we will break the code into several parts, which all are occurring before showing the File successfully uploaded message box.
- First, let's check whether the newly uploaded file has already existed within our file list (replacing an old file on the FTP server). If it does, then we can skip the entire thing; otherwise, append the filename to our fileList string list, as shown in the following code:
// Add new file to file list array if not exist yet bool exists = false; if (fileList.size() > 0) { for (int i = 0; i < fileList.size(); i++) { if (fileList.at(i) == uploadFileName) { exists = true; } } } if (!exists) { fileList.append(uploadFileName); }
- After that, create a temporary text file (files.txt) in our application's directory and save the new file list in the text file:
// Create new files.txt QString fileName = "files.txt"; QFile* file = new QFile(qApp->applicationDirPath() + "/" + fileName); file->open(QIODevice::ReadWrite); if (fileList.size() > 0) { for (int j = 0; j < fileList.size(); j++) { if (fileList.at(j) != "") { file->write(QString(fileList.at(j) + ",").toUtf8()); } } } file->close();
- Finally, we use the QFile class to open the text file we just created, and we upload it again to the FTP server to replace the old file list:
// Re-open the file QFile* newFile = new QFile(qApp->applicationDirPath() + "/" + fileName); if (newFile->open(QIODevice::ReadOnly)) { // Update file list to server QUrl ftpPath; ftpPath.setUrl(ftpAddress + fileName); ftpPath.setUserName(username); ftpPath.setPassword(password); ftpPath.setPort(ftpPort); QNetworkRequest request; request.setUrl(ftpPath); uploadFileListReply = manager->put(request, newFile); connect(uploadFileListReply, SIGNAL(finished()), this, SLOT(uploadFileListFinished())); file->close(); }
- Again, we use the SIGNAL and SLOT mechanisms so that we are notified when the file list has been uploaded. The slot function uploadFileListFinished() looks something like the following:
void MainWindow::uploadFileListFinished() { if(uploadFileListReply->error() != QNetworkReply::NoError) { QMessageBox::warning(this, "Failed", "Failed to update file list: " + uploadFileListReply->errorString()); } else { getFileList(); } }
- We basically just call getFileList() again after we have updated the file list into the FTP server. If you build and run the project now, you should be able to upload your first file to your local FTP server, hooray!
![](Images/9f62c8f3-6cf9-42aa-8a69-8d79ea69d13b.png)