C ++ Qt QFileSystemWatcher загрузка файла дважды

У меня возникли проблемы, когда файл загружается дважды на сервер.

Я использую класс QFileSystemWatcher из C ++ Qt в Windows XP для отправки файла при изменении папки. Файлы имеют небольшой размер (1-12 КБ).

Приложение отправляет файлы путем сканирования папки при каждом ее изменении (по сигналу directoryChanged), перебирает файлы и отправляет тот, который мне нужен. Сервер отвечает XML-файлом, который возвращается в ту же папку для другого приложения, чтобы обработать его.

По-видимому, происходит то, что в некоторых системах одновременно происходит два очень быстрых сигнала directoryChanged и происходит две очень быстрые загрузки файлов.

Сервер работает под управлением Apache и PHP, и на стороне PHP имеется простой MUTEX, но я просто хотел найти причину проблемы, которая, похоже, связана с Qt.
Я открыт для использования другого класса, другой библиотеки или C ++.

Вот некоторый код, я удалил весь нерелевантный контент:

this->w = new QFileSystemWatcher();
this->w->addPath("C:/POSERA/MaitreD/DATA/INT");

QStringList directoryList = w->directories();
Q_FOREACH(QString directory, directoryList)
{
qDebug() << "Watching Main Directory name: " << directory << endl;
}

DirectoryWatcher* dw = new DirectoryWatcher;

QObject::connect( this->w, SIGNAL(directoryChanged(const QString&)),
dw, SLOT(directoryChanged(const QString&)));

и DirectoryWatcher.cpp:

DirectoryWatcher::DirectoryWatcher(QWidget* parent) : QWidget(parent)
{
lockSend = false;
}

void DirectoryWatcher::directoryChanged(const QString& str)
{
directoryLastChanged = str;

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

sendChangedFiles(cString);
}

void DirectoryWatcher::sendChangedFiles(const char* path)
{
DIR *dir;
struct dirent *ent;
if ((dir = opendir (path)) != NULL)
{
QString str;

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

QFileInfo info(str);

if (lockSend == false &&
(info.completeSuffix() == "xml" || info.completeSuffix() == "XML") &&
(info.baseName() != "") &&
(!info.baseName().startsWith("REDM")) &&
(!info.baseName().startsWith("REFT")))
{
// reset the counter.
this->resendCounter = 0;

sendFileAndAccept(str.toUtf8().constData());
}
}
closedir (dir);
}
else
{
qDebug() << "Could not open directory" << endl;
}
}

class QNetworkRequest;
class QNetworkReply;

void DirectoryWatcher::sendFileAndAccept(const char* path)
{
// increment the resend counter
this->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(path);
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart

multiPart->append(filePart);

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

multiPart->setParent(reply); // delete the multiPart with the reply

// lock
lockSend = true;
}

void DirectoryWatcher::saveResponse(QNetworkReply *rep) {

// get the response
QByteArray bts = rep->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() << "new path: " << newPath << endl;

switch (rep->error()) {
case QNetworkReply::NoError: {
qDebug() << "NO ERROR" << endl;

// save response to a file.

QFile file(newPath);
file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out << str;

file.close();

break;
}
default:

//        case QNetworkReply::TimeoutError :
//        case QNetworkReply::HostNotFoundError :
qDebug() << "NETWORK REPLY ERROR" << endl;
// resend the file if the counter is < 10
if (this->resendCounter < 5) {

// delay by n sec
QTime dieTime = QTime::currentTime().addSecs(1);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

sendFileAndAccept(this->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() << "Saving file for later..." << endl;
if (!saveFileForLater(lastPathSent.toStdString().c_str())) {
qDebug() << "ERROR SAVING FILE, CHECK IF FOLDER EXISTS AND THE PERMISSIONS." << endl;
}

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

break;
}

// unlock
lockSend = false;

rep->deleteLater(); // prevent memory leak
}

bool DirectoryWatcher::saveFileForLater(const char* pathToRequestFile) {

QFile file(pathToRequestFile);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "readonly and text" << endl;
return false;
}

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

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

return file.copy(newPath);

}

Спасибо за вашу помощь.

2

Решение

Наиболее вероятная причина двух выпусков directoryChanged заключается в том, что обычный редактор при сохранении изменений удаляет и записывает новую версию файла на диск. Вот почему есть один сигнал, когда файл удаляется, и один, когда он воссоздается.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]