30 #include <boost/regex.hpp>
32 #include <IceUtil/UUID.h>
42 namespace fs = std::filesystem;
45 databasePrx(databasePrx)
48 if (!armarxCachePath.empty())
50 init(armarxCachePath);
54 static std::string cachePath =
55 (std::filesystem::temp_directory_path() /
std::to_string(std::random_device{}()))
62 const std::string& cachePath) :
63 databasePrx(databasePrx)
79 if (!fs::exists(cachePath))
81 fs::create_directory(cachePath);
84 fileCachePath = fs::path(cachePath) / fs::path(
"files");
86 if (!fs::exists(fileCachePath))
88 fs::create_directory(fileCachePath);
92 if (!fileCachePath.is_absolute())
95 std::filesystem::path fullPath(std::filesystem::current_path());
96 fileCachePath = fullPath / fileCachePath;
103 return fileCachePath.string();
108 std::string& cacheFileName,
109 bool preserveOriginalName)
121 fs::path filenameFromProxy(filePrx->getFilename());
123 fs::path localFile = fileCachePath / filenameFromProxy.stem();
125 if (!preserveOriginalName)
127 localFile += fs::path(filePrx->getId() +
"_" + filePrx->getMD5());
129 std::string localFileStr = localFile.string();
130 std::string extensionStr = filenameFromProxy.extension().string();
131 localFile = fs::path(localFileStr + extensionStr);
134 bool cached = fs::exists(localFile);
138 cached = cached && ((std::uintmax_t)filePrx->getFileSize() == fs::file_size(localFile));
141 fs::file_time_type lwt = fs::last_write_time(localFile);
142 auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
143 lwt - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
144 time_t time = std::chrono::system_clock::to_time_t(sctp);
146 cached = cached && (!preserveOriginalName || (time >= filePrx->getUploadDate() / 1000));
156 std::filesystem::path filePath;
157 filePath = localFile;
158 filePath = filePath.parent_path();
159 create_directories(filePath);
162 const std::string tmpLocalFile = localFile.string() + IceUtil::generateUUID() +
".part";
164 fsOut.open(tmpLocalFile.c_str(), std::ios_base::out | std::ios_base::binary);
166 memoryx::Blob buffer;
169 while (filePrx->getNextChunk(buffer))
171 fsOut.write((
char*)&buffer[0], buffer.size());
175 fs::rename(tmpLocalFile, localFile);
178 cacheFileName = localFile.string();
184 std::string& cacheFileName,
185 bool preserveOriginalName)
189 GridFileInterfacePrx filePrx = getFileProxyFromAttr(fileAttr);
198 databasePrx->releaseFileProxy(filePrx);
204 std::vector<std::string>& cacheFileNames,
205 bool preserveOriginalNames )
210 GridFileList filePrxList = getFileProxiesFromAttr(fileAttr);
212 if (filePrxList.empty())
217 std::string cacheFileName;
219 for (GridFileList::iterator it = filePrxList.begin(); it != filePrxList.end(); ++it)
223 cacheFileNames.push_back(cacheFileName);
224 databasePrx->releaseFileProxy(*it);
232 bool preserveOriginalNames )
235 std::vector<std::string> cacheFileNames;
243 std::string cacheFileName;
248 fs.open(cacheFileName.c_str(), std::ios_base::in);
259 GridFileInterfacePrx filePrx = getFileProxyFromAttr(fileAttr);
261 databasePrx->releaseFileProxy(filePrx);
267 const std::string& localFileName,
268 EntityAttributeBasePtr& fileAttr,
269 const std::string& gridFSName )
272 return addFileToAttr(filesDBName, localFileName, fileAttr, gridFSName);
277 const std::string& localFileName,
278 EntityAttributeBasePtr& fileAttr,
279 const std::string& gridFSName )
282 std::filesystem::path fname(localFileName);
283 fname = std::filesystem::absolute(fname);
288 fileId = databasePrx->storeFile(
291 (gridFSName.empty() ? fname.filename().string() : gridFSName));
293 catch (
const FileNotFoundException& e)
297 std::ifstream fin(fname.string().c_str(), std::ios::binary);
300 throw FileNotFoundException(
"File not found: " + fname.string(), fname.string());
302 std::stringstream contentStream;
303 contentStream << fin.rdbuf();
304 fileId = databasePrx->storeTextFile(
307 (gridFSName.empty() ? fname.filename().string() : gridFSName));
313 fileAttr->addValue(fileVar);
320 const std::string& localDirectoryName,
321 EntityAttributeBasePtr& fileAttr,
322 std::string excludeFilter)
325 boost::regex exclude(excludeFilter.c_str());
330 std::filesystem::path relativePathBase = localDirectoryName;
331 relativePathBase = relativePathBase.parent_path();
334 for (std::filesystem::recursive_directory_iterator end, dir(localDirectoryName.c_str());
339 if (dir->status().type() != std::filesystem::file_type::directory)
341 if (boost::regex_match(dir->path().filename().c_str(), exclude))
343 dir.disable_recursion_pending();
347 std::string fileName = makeRelativePath(dir->path(), relativePathBase);
350 const std::string fileId =
351 addFileToAttr(filesDBName, dir->path().c_str(), fileAttr, fileName);
352 success &= !fileId.empty();
362 const std::string& localBaseDirectoryName,
363 const std::vector<std::string>& localFiles,
364 EntityAttributeBasePtr& fileAttr)
370 std::filesystem::path relativePathBase = localBaseDirectoryName;
371 relativePathBase = relativePathBase.parent_path();
373 for (
size_t i = 0; i < localFiles.size(); i++)
375 std::filesystem::path f = localFiles[i];
376 std::string fileName = makeRelativePath(f, relativePathBase);
378 const std::string fileId =
addFileToAttr(filesDBName, f.c_str(), fileAttr, fileName);
379 success &= !fileId.empty();
389 const MongoDBRefPtr fileRef = extractMongoDBRef(fileAttr->getValueAt(fileIndex));
396 return databasePrx->removeFileById(fileRef->dbName, fileRef->docId);
410 for (
size_t i = 0; i < (size_t)fileAttr->size(); ++i)
419 GridFileManager::getFileProxyFromAttr(
const AttributeBasePtr& attr)
const
426 return databasePrx->getFileProxyById(fileRef->dbName, fileRef->docId);
430 ARMARX_WARNING <<
"Could not get fileref for attribute " << attr->getName();
431 return GridFileInterfacePrx();
436 GridFileManager::getFileProxiesFromAttr(
const AttributeBasePtr& attr)
const
447 for (
size_t i = 0; i < (size_t)entityAttr->size(); ++i)
449 const MongoDBRefPtr fileRef = extractMongoDBRef(entityAttr->getValueAt(i));
453 const GridFileInterfacePrx prx =
454 databasePrx->getFileProxyById(fileRef->dbName, fileRef->docId);
455 result.push_back(prx);
463 GridFileManager::extractMongoDBRef(
const AttributeBasePtr& attr)
const
473 return extractMongoDBRef(entityAttr->getValue());
505 GridFileManager::makeRelativePath(
const std::filesystem::path& directory,
506 const std::filesystem::path& basePath)
509 std::filesystem::path diffpath;
510 std::filesystem::path tmppath = directory;
512 while (tmppath != basePath)
514 diffpath = tmppath.filename() / diffpath;
515 tmppath = tmppath.parent_path();
520 diffpath = directory;
525 return diffpath.string();