<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[C++ Qt QFileSystemWatcher file upload double]]></title><description><![CDATA[<p dir="auto">I am having issues where the file is being uploaded twice to the server.</p>
<p dir="auto">I am using the QFileSystemWatcher class from C++ Qt on Windows XP to send a file when the folder changes The files are small (1-12kb).</p>
<p dir="auto">The application sends the files by scanning the folder whenever it changes (on directoryChanged signal), loop through the files and send the one that I need. The server responds with an xml file that is returned into the same folder for another application to processes it.</p>
<p dir="auto">Apparently what’s happening is that on some systems there are 2 very fast directoryChanged signals at nearly the same time and there are two very fast file uploads happening.</p>
<p dir="auto">The server is running Apache and PHP, and there’s a simple MUTEX in place on the PHP side, but I just wanted to get to the root of the problem which seems to be on the Qt side. I'm open to using another class, another library or straight C++.</p>
<p dir="auto">Here is some code, I stripped all the irrelevant content:<br />
<a class="plugin-mentions-user plugin-mentions-a" href="/user/this">@<bdi>this-</bdi></a>&gt;w = new QFileSystemWatcher();<br />
this-&gt;w-&gt;addPath("C:/POSERA/MaitreD/DATA/INT");</p>
<p dir="auto">QStringList directoryList = w-&gt;directories();<br />
Q_FOREACH(QString directory, directoryList)<br />
qDebug() &lt;&lt; "Watching Main Directory name: " &lt;&lt; directory &lt;&lt; endl;</p>
<p dir="auto">DirectoryWatcher* dw = new DirectoryWatcher;</p>
<p dir="auto">QObject::connect(<br />
this-&gt;w, SIGNAL(directoryChanged(const QString&amp;)),<br />
dw, SLOT(directoryChanged(const QString&amp;))<br />
);@</p>
]]></description><link>https://forum.qt.io/topic/31065/c-qt-qfilesystemwatcher-file-upload-double</link><generator>RSS for Node</generator><lastBuildDate>Fri, 12 Jun 2026 13:50:05 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/31065.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 23 Aug 2013 04:19:51 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to C++ Qt QFileSystemWatcher file upload double on Fri, 23 Aug 2013 04:20:05 GMT]]></title><description><![CDATA[<p dir="auto">and the DirectoryWatcher.cpp:<br />
@DirectoryWatcher::DirectoryWatcher(QWidget* parent) : QWidget(parent)<br />
{<br />
lockSend = false;<br />
}</p>
<p dir="auto">void DirectoryWatcher::directoryChanged(const QString&amp; str) {</p>
<pre><code>directoryLastChanged = str;

QByteArray byteArray = str.toUtf8();
const char* cString = byteArray.constData();

sendChangedFiles(cString);
</code></pre>
<p dir="auto">}</p>
<p dir="auto">void DirectoryWatcher::sendChangedFiles(const char* path) {</p>
<pre><code>DIR *dir;
struct dirent *ent;
if ((dir = opendir (path)) != NULL) {

    QString str;

    while ((ent = readdir (dir)) != NULL) {
        str = QString("%1/%2").arg(path, ent-&gt;d_name);

        QFileInfo info(str);



        if (lockSend == false &amp;&amp; (info.completeSuffix() == "xml" || info.completeSuffix() == "XML") &amp;&amp; info.baseName() != "" &amp;&amp; !info.baseName().startsWith("REDM") &amp;&amp; !info.baseName().startsWith("REFT")) {

            // reset the counter.
            this-&gt;resendCounter = 0;

            sendFileAndAccept(str.toUtf8().constData());

        }

    }

    closedir (dir);
} else {
    qDebug() &lt;&lt; "Could not open directory" &lt;&lt; endl;
}
</code></pre>
<p dir="auto">}</p>
<p dir="auto">class QNetworkRequest;<br />
class QNetworkReply;<br />
void DirectoryWatcher::sendFileAndAccept(const char* path) {</p>
<pre><code>// increment the resend counter
this-&gt;resendCounter++;

QFileInfo fileInfo(path);

QNetworkAccessManager * mgr = new QNetworkAccessManager(this);
connect(mgr,SIGNAL(finished(QNetworkReply*)),this,SLOT(saveResponse(QNetworkReply*)));
connect(mgr,SIGNAL(finished(QNetworkReply*)),mgr,SLOT(deleteLater())); // @todo delete later

QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/xml")); // @todo test
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"someFile\"; filename=\"" + fileInfo.baseName() + ".xml\""));

currentFileSent = fileInfo.baseName();

QFile *file = new QFile&amp;#40;path&amp;#41;;
file-&gt;open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file-&gt;setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart

multiPart-&gt;append(filePart);

// POST request
QNetworkReply *reply = mgr-&gt;post(QNetworkRequest(QUrl(XXXXXX)), multiPart);

multiPart-&gt;setParent(reply); // delete the multiPart with the reply

// lock
lockSend = true;
</code></pre>
<p dir="auto">}</p>
<p dir="auto">void DirectoryWatcher::saveResponse(QNetworkReply *rep) {</p>
<pre><code>// get the response
QByteArray bts = rep-&gt;readAll();
QString str(bts);

// compute new path
QString partName = currentFileSent.mid(1, currentFileSent.length());
QString newPath = QString("%1/A%2.xml").arg(directoryLastChanged, partName);

qDebug() &lt;&lt; "new path: " &lt;&lt; newPath &lt;&lt; endl;

switch (rep-&gt;error()) {
    case QNetworkReply::NoError: {
        qDebug() &lt;&lt; "NO ERROR" &lt;&lt; endl;

        // save response to a file.

        QFile file&amp;#40;newPath&amp;#41;;
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&amp;file);
        out &lt;&lt; str;

        file.close();

        break;
    }
    default:
</code></pre>
<p dir="auto">//        case QNetworkReply::TimeoutError :<br />
//        case QNetworkReply::HostNotFoundError :<br />
qDebug() &lt;&lt; "NETWORK REPLY ERROR" &lt;&lt; endl;<br />
// resend the file if the counter is &lt; 10<br />
if (this-&gt;resendCounter &lt; 5) {</p>
<pre><code>            // delay by n sec
            QTime dieTime = QTime::currentTime().addSecs(1);
            while( QTime::currentTime() &lt; dieTime )
                QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

            sendFileAndAccept(this-&gt;lastPathSent.toStdString().c_str());
        } else {

            // after 10 attempts, we're probably sure that the network is down
            // save the file somewhere and generate a default one to prevent timeouts.

            qDebug() &lt;&lt; "Saving file for later..." &lt;&lt; endl;
            if (!saveFileForLater(lastPathSent.toStdString().c_str())) {
                qDebug() &lt;&lt; "ERROR SAVING FILE, CHECK IF FOLDER EXISTS AND THE PERMISSIONS." &lt;&lt; endl;
            }

            // generate a default one to prevent timeouts.
            qDebug() &lt;&lt; "Generate a default file..." &lt;&lt; endl;
            // ...
        }

        break;
}

// unlock
lockSend = false;

rep-&gt;deleteLater(); // prevent memory leak
</code></pre>
<p dir="auto">}</p>
<p dir="auto">bool DirectoryWatcher::saveFileForLater(const char* pathToRequestFile) {</p>
<pre><code>QFile file&amp;#40;pathToRequestFile&amp;#41;;
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
    qDebug() &lt;&lt; "readonly and text" &lt;&lt; endl;
    return false;
}

QString path(pathToRequestFile);
QFileInfo fileinfo(path);

QString newPath = "C:\\data\\offline\\" + fileinfo.fileName();

return file.copy(newPath);
</code></pre>
<p dir="auto">}@</p>
]]></description><link>https://forum.qt.io/post/192220</link><guid isPermaLink="true">https://forum.qt.io/post/192220</guid><dc:creator><![CDATA[Sk1F0x]]></dc:creator><pubDate>Fri, 23 Aug 2013 04:20:05 GMT</pubDate></item></channel></rss>