diff --git a/src/data_transfer.cpp b/src/data_transfer.cpp
index c977b542bae86f16fe6847193ff8fcb106f024e6..696a7f293de832c0d76582c24c854ebfffd1d553 100644
--- a/src/data_transfer.cpp
+++ b/src/data_transfer.cpp
@@ -1200,20 +1200,20 @@ TransferManager::onIncomingFileTransfer(const std::string& fileId,
         return;
     }
 
-    auto symlinkPath = path(fileId);
+    auto filelinkPath = path(fileId);
 
     DRing::DataTransferInfo info;
     info.accountId = pimpl_->accountId_;
     info.conversationId = pimpl_->to_;
     info.path = itW->second.path;
     if (info.path.empty())
-        info.path = symlinkPath;
+        info.path = filelinkPath;
     info.totalSize = itW->second.totalSize;
     info.bytesProgress = 0;
 
     // Create symlink for future transfers
-    if (info.path != symlinkPath && !fileutils::isSymLink(symlinkPath))
-        fileutils::createSymLink(symlinkPath, info.path);
+    if (info.path != filelinkPath && !fileutils::isSymLink(filelinkPath))
+        fileutils::createFileLink(filelinkPath, info.path);
 
     auto ifile = std::make_shared<IncomingFile>(std::move(channel),
                                                 info,
diff --git a/src/fileutils.cpp b/src/fileutils.cpp
index c802152103265a6c8f0acd39d07c50a888a6ea40..d7f5786195e9bd7735726fd7d233ffbe39d09d01 100644
--- a/src/fileutils.cpp
+++ b/src/fileutils.cpp
@@ -317,16 +317,25 @@ writeTime(const std::string& path)
 }
 
 void
-createSymLink(const std::string& linkFile, const std::string& target)
+createFileLink(const std::string& linkFile, const std::string& target, bool hard)
 {
-    auto sep = target.find_last_of('/');
-    if (sep != std::string::npos)
-        check_dir(target.substr(0, sep).c_str());
 #ifndef _WIN32
-    symlink(target.c_str(), linkFile.c_str());
+    int status;
+    if (hard)
+        status = link(target.c_str(), linkFile.c_str());
+    else
+        status = symlink(target.c_str(), linkFile.c_str());
+    if (status != 0)
+        JAMI_ERR("Couldn't create %s link: ", (hard ? "hard" : "soft"), strerror(errno));
 #else
-    std::error_code ec;
-    std::filesystem::create_symlink(target, linkFile, ec);
+    try {
+        if (hard)
+            std::filesystem::create_hard_link(target, linkFile);
+        else
+            std::filesystem::create_symlink(target, linkFile);
+    } catch (const std::exception& e) {
+        JAMI_ERR("Couldn't create %s link: ", (hard ? "hard" : "soft"), e.what());
+    }
 #endif
 }
 
@@ -458,7 +467,7 @@ dirent_buf_size(UNUSED DIR* dirp)
 #if defined(NAME_MAX)
         name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
 #else
-        return (size_t)(-1);
+        return (size_t) (-1);
 #endif
 #else
 #if defined(NAME_MAX)
@@ -479,7 +488,7 @@ readDirectory(const std::string& dir)
         return {};
 
     size_t size = dirent_buf_size(dp);
-    if (size == (size_t)(-1))
+    if (size == (size_t) (-1))
         return {};
     std::vector<uint8_t> buf(size);
     dirent* entry;
diff --git a/src/fileutils.h b/src/fileutils.h
index 677ea18fedca65a3e6da3e625c591e77ef86fddf..31c134d304fc9c6e9930727dc294b89e33652a08 100644
--- a/src/fileutils.h
+++ b/src/fileutils.h
@@ -85,7 +85,7 @@ bool isSymLink(const std::string& path);
 
 std::chrono::system_clock::time_point writeTime(const std::string& path);
 
-void createSymLink(const std::string& src, const std::string& dest);
+void createFileLink(const std::string& src, const std::string& dest, bool hard = false);
 
 std::string getFileExtension(const std::string& filename);
 
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 82e6b962a50cad31cb8e828e301652914104aefc..cc1a520dcb5a6b4796e8781ee6ab745b37925493 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -5344,16 +5344,17 @@ JamiAccount::sendFile(const std::string& conversationId,
                                  tid,
                                  path](bool, const std::string& commitId) {
                                     // Create a symlink to answer to re-ask
-                                    auto symlinkPath = fileutils::get_data_dir() + DIR_SEPARATOR_STR
-                                                       + accId + DIR_SEPARATOR_STR
-                                                       + "conversation_data" + DIR_SEPARATOR_STR
-                                                       + conversationId + DIR_SEPARATOR_STR
-                                                       + commitId + "_" + std::to_string(tid);
+                                    auto filelinkPath = fileutils::get_data_dir()
+                                                        + DIR_SEPARATOR_STR + accId
+                                                        + DIR_SEPARATOR_STR + "conversation_data"
+                                                        + DIR_SEPARATOR_STR + conversationId
+                                                        + DIR_SEPARATOR_STR + commitId + "_"
+                                                        + std::to_string(tid);
                                     auto extension = fileutils::getFileExtension(path);
                                     if (!extension.empty())
-                                        symlinkPath += "." + extension;
-                                    if (path != symlinkPath && !fileutils::isSymLink(symlinkPath))
-                                        fileutils::createSymLink(symlinkPath, path);
+                                        filelinkPath += "." + extension;
+                                    if (path != filelinkPath && !fileutils::isSymLink(filelinkPath))
+                                        fileutils::createFileLink(filelinkPath, path, true);
                                 });
         }
     });