i having issues file being uploaded twice server.
i using qfilesystemwatcher class c++ qt on windows xp send file when folder changes files small (1-12kb).
the application sends files scanning folder whenever changes (on directorychanged signal), loop through files , send 1 need. server responds xml file returned same folder application processes it.
apparently what’s happening on systems there 2 fast directorychanged signals @ same time , there 2 fast file uploads happening.
the server running apache , php, , there’s simple mutex in place on php side, wanted root of problem seems on qt side. i'm open using class, library or straight c++.
here code, stripped irrelevant content:
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&)));
and 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 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 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); // cannot delete file now, delete multipart multipart->append(filepart); // post request qnetworkreply *reply = mgr->post(qnetworkrequest(qurl(xxxxxx)), multipart); multipart->setparent(reply); // delete multipart reply // lock locksend = true; } void directorywatcher::saveresponse(qnetworkreply *rep) { // 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 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 file if counter < 10 if (this->resendcounter < 5) { // delay 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 sure network down // save file somewhere , generate default 1 prevent timeouts. qdebug() << "saving file later..." << endl; if (!savefileforlater(lastpathsent.tostdstring().c_str())) { qdebug() << "error saving file, check if folder exists , permissions." << endl; } // generate default 1 prevent timeouts. qdebug() << "generate 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 , text" << endl; return false; } qstring path(pathtorequestfile); qfileinfo fileinfo(path); qstring newpath = "c:\\data\\offline\\" + fileinfo.filename(); return file.copy(newpath); }
thanks help.
the possible reason 2 emits of directorychanged normal editor when saving changes removes , writes new version of file disk. that's why there 1 signal when file removed , 1 when it's recreated.