diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 17770fc91..90a923d53 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -3125,8 +3125,9 @@ void ApiWrap::toggleFavedSticker(
 		return;
 	}
 
-	auto failHandler = std::make_shared<Fn<void(const RPCError&)>>();
+	auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
 	auto performRequest = [=] {
+		const auto usedFileReference = document->fileReference();
 		request(MTPmessages_FaveSticker(
 			document->mtpInput(),
 			MTP_bool(!faved)
@@ -3134,16 +3135,15 @@ void ApiWrap::toggleFavedSticker(
 			if (mtpIsTrue(result)) {
 				Stickers::SetFaved(document, faved);
 			}
-		}).fail(
-			base::duplicate(*failHandler)
-		).send();
+		}).fail([=](const RPCError &error) {
+			(*failHandler)(error, usedFileReference);
+		}).send();
 	};
-	*failHandler = [=](const RPCError &error) {
+	*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
 		if (error.code() == 400
 			&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
-			const auto current = document->fileReference();
 			auto refreshed = [=](const UpdatedFileReferences &data) {
-				if (document->fileReference() != current) {
+				if (document->fileReference() != usedFileReference) {
 					performRequest();
 				}
 			};
@@ -3161,8 +3161,9 @@ void ApiWrap::toggleSavedGif(
 		return;
 	}
 
-	auto failHandler = std::make_shared<Fn<void(const RPCError&)>>();
+	auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
 	auto performRequest = [=] {
+		const auto usedFileReference = document->fileReference();
 		request(MTPmessages_SaveGif(
 			document->mtpInput(),
 			MTP_bool(!saved)
@@ -3172,16 +3173,15 @@ void ApiWrap::toggleSavedGif(
 					App::addSavedGif(document);
 				}
 			}
-		}).fail(
-			base::duplicate(*failHandler)
-		).send();
+		}).fail([=](const RPCError &error) {
+			(*failHandler)(error, usedFileReference);
+		}).send();
 	};
-	*failHandler = [=](const RPCError &error) {
+	*failHandler = [=](const RPCError & error, QByteArray usedFileReference) {
 		if (error.code() == 400
 			&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
-			const auto current = document->fileReference();
 			auto refreshed = [=](const UpdatedFileReferences &data) {
-				if (document->fileReference() != current) {
+				if (document->fileReference() != usedFileReference) {
 					performRequest();
 				}
 			};
@@ -4902,8 +4902,9 @@ void ApiWrap::sendExistingDocument(
 		caption,
 		MTPReplyMarkup());
 
-	auto failHandler = std::make_shared<Fn<void(const RPCError&)>>();
+	auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
 	auto performRequest = [=] {
+		const auto usedFileReference = document->fileReference();
 		history->sendRequestId = request(MTPmessages_SendMedia(
 			MTP_flags(sendFlags),
 			peer->input,
@@ -4918,17 +4919,16 @@ void ApiWrap::sendExistingDocument(
 			sentEntities
 		)).done([=](const MTPUpdates &result) {
 			applyUpdates(result, randomId);
-		}).fail(
-			base::duplicate(*failHandler)
-		).afterRequest(history->sendRequestId
+		}).fail([=](const RPCError &error) {
+			(*failHandler)(error, usedFileReference);
+		}).afterRequest(history->sendRequestId
 		).send();
 	};
-	*failHandler = [=](const RPCError &error) {
+	*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
 		if (error.code() == 400
 			&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
-			const auto current = document->fileReference();
 			auto refreshed = [=](const UpdatedFileReferences &data) {
-				if (document->fileReference() != current) {
+				if (document->fileReference() != usedFileReference) {
 					performRequest();
 				} else {
 					sendMessageFail(error);
diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp
index 812ace968..c28e48dba 100644
--- a/Telegram/SourceFiles/data/data_document.cpp
+++ b/Telegram/SourceFiles/data/data_document.cpp
@@ -1195,12 +1195,14 @@ auto DocumentData::createStreamingLoader(Data::FileOrigin origin) const
 	return hasRemoteLocation()
 		? std::make_unique<Media::Streaming::LoaderMtproto>(
 			&session().api(),
-			_dc,
-			MTP_inputDocumentFileLocation(
-				MTP_long(id),
-				MTP_long(_access),
-				MTP_bytes(_fileReference),
-				MTP_string(QString())),
+			StorageFileLocation(
+				_dc,
+				session().userId(),
+				MTP_inputDocumentFileLocation(
+					MTP_long(id),
+					MTP_long(_access),
+					MTP_bytes(_fileReference),
+					MTP_string(QString()))),
 			size,
 			origin)
 		: nullptr;
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
index 6e1a6d443..060217235 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.cpp
@@ -8,44 +8,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "media/streaming/media_streaming_loader_mtproto.h"
 
 #include "apiwrap.h"
+#include "auth_session.h"
 #include "storage/cache/storage_cache_types.h"
 
 namespace Media {
 namespace Streaming {
 namespace {
 
-constexpr auto kMaxConcurrentRequests = 2;
-constexpr auto kDocumentBaseCacheTag = 0x0000000000010000ULL;
-constexpr auto kDocumentBaseCacheMask = 0x000000000000FF00ULL;
+constexpr auto kMaxConcurrentRequests = 4;
 
 } // namespace
 
 LoaderMtproto::LoaderMtproto(
 	not_null<ApiWrap*> api,
-	MTP::DcId dcId,
-	const MTPInputFileLocation &location,
+	const StorageFileLocation &location,
 	int size,
 	Data::FileOrigin origin)
 : _api(api)
-, _dcId(dcId)
 , _location(location)
 , _size(size)
 , _origin(origin) {
 }
 
 std::optional<Storage::Cache::Key> LoaderMtproto::baseCacheKey() const {
-	return _location.match([&](const MTPDinputDocumentFileLocation &data) {
-		const auto id = data.vid.v;
-		const auto high = kDocumentBaseCacheTag
-			| ((uint64(_dcId) << 16) & kDocumentBaseCacheMask)
-			| (id >> 48);
-		const auto low = (id << 16);
-
-		Ensures((low & 0xFFULL) == 0);
-		return Storage::Cache::Key{ high, low };
-	}, [](auto &&) -> Storage::Cache::Key {
-		Unexpected("Not implemented file location type.");
-	});
+	return _location.bigFileBaseCacheKey();
 }
 
 int LoaderMtproto::size() const {
@@ -99,18 +85,19 @@ void LoaderMtproto::sendNext() {
 	}
 
 	static auto DcIndex = 0;
-	const auto reference = locationFileReference();
+	const auto usedFileReference = _location.fileReference();
 	const auto id = _sender.request(MTPupload_GetFile(
-		_location,
+		_location.tl(Auth().userId()),
 		MTP_int(offset),
 		MTP_int(kPartSize)
 	)).done([=](const MTPupload_File &result) {
 		requestDone(offset, result);
 	}).fail([=](const RPCError &error) {
-		requestFailed(offset, error, reference);
-	}).toDC(
-		MTP::downloadDcId(_dcId, (++DcIndex) % MTP::kDownloadSessionsCount)
-	).send();
+		requestFailed(offset, error, usedFileReference);
+	}).toDC(MTP::downloadDcId(
+		_location.dcId(),
+		(++DcIndex) % MTP::kDownloadSessionsCount
+	)).send();
 	_requests.emplace(offset, id);
 
 	sendNext();
@@ -155,43 +142,20 @@ void LoaderMtproto::requestFailed(
 		return fail();
 	}
 	const auto callback = [=](const Data::UpdatedFileReferences &updated) {
-		_location.match([&](const MTPDinputDocumentFileLocation &location) {
-			const auto i = updated.data.find(
-				Data::DocumentFileLocationId{ location.vid.v });
-			if (i == end(updated.data)) {
-				return fail();
-			}
-			const auto reference = i->second;
-			if (reference == usedFileReference) {
-				return fail();
-			} else if (reference != location.vfile_reference.v) {
-				_location = MTP_inputDocumentFileLocation(
-					MTP_long(location.vid.v),
-					MTP_long(location.vaccess_hash.v),
-					MTP_bytes(reference),
-					MTP_string(QString()));
-			}
-			if (!_requests.take(offset)) {
-				// Request with such offset was already cancelled.
-				return;
-			}
+		_location.refreshFileReference(updated);
+		if (_location.fileReference() == usedFileReference) {
+			fail();
+		} else if (!_requests.take(offset)) {
+			// Request with such offset was already cancelled.
+			return;
+		} else {
 			_requested.add(offset);
 			sendNext();
-		}, [](auto &&) {
-			Unexpected("Not implemented file location type.");
-		});
+		}
 	};
 	_api->refreshFileReference(_origin, crl::guard(this, callback));
 }
 
-QByteArray LoaderMtproto::locationFileReference() const {
-	return _location.match([&](const MTPDinputDocumentFileLocation &data) {
-		return data.vfile_reference.v;
-	}, [](auto &&) -> QByteArray {
-		Unexpected("Not implemented file location type.");
-	});
-}
-
 rpl::producer<LoadedPart> LoaderMtproto::parts() const {
 	return _parts.events();
 }
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h
index c2a9058d6..83300f6c6 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_loader_mtproto.h
@@ -20,8 +20,7 @@ class LoaderMtproto : public Loader, public base::has_weak_ptr {
 public:
 	LoaderMtproto(
 		not_null<ApiWrap*> api,
-		MTP::DcId dcId,
-		const MTPInputFileLocation &location,
+		const StorageFileLocation &location,
 		int size,
 		Data::FileOrigin origin);
 
@@ -44,8 +43,8 @@ private:
 
 	void requestDone(int offset, const MTPupload_File &result);
 	void requestFailed(
-		int offset, 
-		const RPCError &error, 
+		int offset,
+		const RPCError &error,
 		const QByteArray &usedFileReference);
 	void changeCdnParams(
 		int offset,
@@ -55,13 +54,11 @@ private:
 		const QByteArray &encryptionIV,
 		const QVector<MTPFileHash> &hashes);
 
-	[[nodiscard]] QByteArray locationFileReference() const;
-
 	const not_null<ApiWrap*> _api;
 	const MTP::DcId _dcId = 0;
 
 	// _location can be changed with an updated file_reference.
-	MTPInputFileLocation _location;
+	StorageFileLocation _location;
 
 	const int _size = 0;
 	const Data::FileOrigin _origin;
diff --git a/Telegram/SourceFiles/ui/image/image_location.cpp b/Telegram/SourceFiles/ui/image/image_location.cpp
index 8b9a545d4..ece1038bb 100644
--- a/Telegram/SourceFiles/ui/image/image_location.cpp
+++ b/Telegram/SourceFiles/ui/image/image_location.cpp
@@ -16,6 +16,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 
 namespace {
 
+constexpr auto kDocumentBaseCacheTag = 0x0000000000010000ULL;
+constexpr auto kDocumentBaseCacheMask = 0x000000000000FF00ULL;
+
 MTPInputPeer GenerateInputPeer(uint64 id, uint64 accessHash, int32 self) {
 	const auto bareId = [&] {
 		return peerToBareMTPInt(id);
@@ -335,6 +338,36 @@ Storage::Cache::Key StorageFileLocation::cacheKey() const {
 	return Key();
 }
 
+Storage::Cache::Key StorageFileLocation::bigFileBaseCacheKey() const {
+	using Key = Storage::Cache::Key;
+
+	// Skip '1' and '2' for legacy document cache keys.
+	const auto shifted = ((uint64(_type) + 3) << 8);
+	const auto sliced = uint64(_dcId) & 0xFFULL;
+	switch (_type) {
+	case Type::Document: {
+		const auto high = kDocumentBaseCacheTag
+			| ((uint64(_dcId) << 16) & kDocumentBaseCacheMask)
+			| (_id >> 48);
+		const auto low = (_id << 16);
+
+		Ensures((low & 0xFFULL) == 0);
+		return Storage::Cache::Key{ high, low };
+	}
+
+	case Type::Legacy:
+	case Type::PeerPhoto:
+	case Type::StickerSetThumb:
+	case Type::Encrypted:
+	case Type::Secure:
+	case Type::Photo:
+	case Type::Takeout:
+		Unexpected("Not implemented file location type.");
+
+	};
+	Unexpected("Invalid file location type.");
+}
+
 QByteArray StorageFileLocation::fileReference() const {
 	return _fileReference;
 }
diff --git a/Telegram/SourceFiles/ui/image/image_location.h b/Telegram/SourceFiles/ui/image/image_location.h
index 3454e154b..e092e7fb1 100644
--- a/Telegram/SourceFiles/ui/image/image_location.h
+++ b/Telegram/SourceFiles/ui/image/image_location.h
@@ -83,6 +83,7 @@ public:
 	[[nodiscard]] Type type() const;
 	[[nodiscard]] bool valid() const;
 	[[nodiscard]] Storage::Cache::Key cacheKey() const;
+	[[nodiscard]] Storage::Cache::Key bigFileBaseCacheKey() const;
 
 	[[nodiscard]] QByteArray fileReference() const;
 	bool refreshFileReference(const Data::UpdatedFileReferences &updates);