- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我遇到文件被两次上传到服务器的问题。
我在 Windows XP 上使用 C++ Qt 的 QFileSystemWatcher 类在文件夹更改时发送文件文件很小 (1-12kb)。
应用程序通过在文件夹发生变化时扫描文件夹来发送文件(在 directoryChanged 信号上),遍历文件并发送我需要的文件。服务器响应一个 xml 文件,该文件返回到同一文件夹中供另一个应用程序处理它。
显然发生的事情是在某些系统上几乎同时有 2 个非常快的 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);
}
感谢您的帮助。
最佳答案
directoryChanged 发出 2 次最可能的原因是普通编辑器在保存更改时会删除文件的新版本并将其写入磁盘。这就是为什么在删除文件时有一个信号,在重新创建文件时有一个信号的原因。
关于C++ Qt QFileSystemWatcher 文件上传双,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18391865/
看似简单,实则行不通。我安装了 usbautomount。 #Watch the media directory and connect to enable save csv pb self.usb_
我有一个 QT 应用程序需要知道特定文件中的新数据何时可用。所以我使用了 QFileSystemWatcher 并将 fileChanged 信号连接到一个函数,该函数将在发生更改时发送消息。 问题是
我有以下问题:我创建了一个 QFileSystemWatcher它在 Linux 上运行良好,但在 Windows 7 上无法正常运行。您能在代码中发现任何可能使其无法工作的内容吗? 谢谢。 这是初始
QFileSystemWatcher watcher; watcher.addPath("C:/watch"); QStringList directoryList = watcher.directo
我正在摆弄 QFileSystemWatcher,跟随 this example .但是在编译时出现 Unresolved external symbol 错误。这是我的代码: #include #
大家好我想使用QFileSystemWatcher递归地观察给定目录及其子目录的变化,但是void QFileSystemWatcher::addPath (const QString & path)
我正在使用 QFileSystemWatcher 来监视我在 watcher->addPath("myPath") 方法中设置的目录中的更改。 当我调用 watcher->directories()
摘自 How do I watch a file for changes? 中的片段: ... @QtCore.pyqtSlot(str) def file_changed(path): pr
在我的文件 console.h/.cpp 中,我有一个小类,它只要求用户输入一些文本,然后再次打印文本,直到用户输入“退出”(参见方法 consoleMain())。然而,在 main.cpp 我也有
我遇到文件被两次上传到服务器的问题。 我在 Windows XP 上使用 C++ Qt 的 QFileSystemWatcher 类在文件夹更改时发送文件文件很小 (1-12kb)。 应用程序通过在文
我是 QT 新手,我想使用 QFileSystemWatcher 来监控文件夹。我只是想不出该怎么做。 我读过 http://qt-project.org/doc/qt-4.8/qfilesystem
我提前道歉,我是 QT 的新手(而且是 C++ 的新手) 我正在尝试设置一个程序,该程序将在特定文件发生更改时执行某个功能。尽管在谷歌上花了几个小时并阅读了 QT 上提供的文档,但我无法找到一种方法让
我有一个 QTreeView,它是通过重新实现 QFileSystemModel 填充的。据我所知,QFileSystemModel 在 rootPath 上安装了一个 QFileSystemWatc
如何从 QFileSystemWatcher directoryChanged 事件中获取更改的文件名? 最佳答案 如果您对文件名更感兴趣,则需要将插槽连接到 fileChanged() 信号而不是
我正在尝试检测由另一个 tcl/python 应用程序修改的文件中的更改。我对文件使用了 QFileSystemWatcher addPath。它不会针对文件更改发出 fileChanged(QStr
这是我的应用程序的基本前提: 我已经建立了一个 QFileSystemWatcher 来监视目录。 Path = [r'C:\Users\user\Documents\Images'] Directo
我有一个 Qt 5 C++ 应用程序,它使用 QFileSystemWatcher 运行很好地监视本地文件。我现在正试图在另一台主机上观看通过 nfs 安装的文件。虽然我的应用可以打开和读取文件,但它
我需要查看qt中的目录。创建了连接。但是当文件被编辑时,发送者会发出两次目录更改信号。 filechanged 信号也同时发出。发射两次信号有什么用?有什么方法可以知道哪个文件/文件夹被更改了?请帮忙
我需要监控一个文件系统,我有一个函数可以递归浏览文件夹和文件,并将它们的路径添加到我的 QFileSystemWatcher 中: void watchFileSystem(const QDir& d
周末我试图解决这个问题,但无济于事。我似乎找不到使用 QFileSystemWatcher::Files() 的示例直接所以我想我会问。 我有一个程序: 让用户选择“来源”文件夹。 按下按钮开始查看源
我是一名优秀的程序员,十分优秀!