diff --git a/release_build_files/readme.md b/release_build_files/readme.md index 2a21483239..c29df4ced4 100644 --- a/release_build_files/readme.md +++ b/release_build_files/readme.md @@ -613,6 +613,10 @@ workflow use only during the development of your app, not for publicly shipping code. ## Release Notes +### Upcoming +- Changes + - Storage (iOS): Handle absolute paths being provided to GetFile. (#1724) + ### 13.0.0 - Changes - General (Android): Update to Firebase Android BoM version 34.0.0. diff --git a/storage/integration_test/src/integration_test.cc b/storage/integration_test/src/integration_test.cc index f430de37de..6626d68c23 100644 --- a/storage/integration_test/src/integration_test.cc +++ b/storage/integration_test/src/integration_test.cc @@ -657,6 +657,28 @@ TEST_F(FirebaseStorageTest, TestPutFileAndGetFile) { EXPECT_NE(future.result(), nullptr); EXPECT_EQ(*future.result(), kSimpleTestFile.size()); + std::vector buffer(kSimpleTestFile.size()); + FILE* file = fopen(path.c_str(), "rb"); + EXPECT_NE(file, nullptr); + size_t bytes_read = std::fread(&buffer[0], 1, kSimpleTestFile.size(), file); + EXPECT_EQ(bytes_read, kSimpleTestFile.size()); + fclose(file); + EXPECT_EQ(memcmp(&kSimpleTestFile[0], &buffer[0], buffer.size()), 0); + } + // Test GetFile without the file prefix to ensure we can download to a file. + { + std::string path = PathForResource() + kGetFileTestFile; + // Try the direct path, which should also work. + std::string file_path = path; + + LogDebug("Saving to local file: %s", path.c_str()); + + firebase::Future future = + RunWithRetry([&]() { return ref.GetFile(file_path.c_str()); }); + WaitForCompletion(future, "GetFile"); + EXPECT_NE(future.result(), nullptr); + EXPECT_EQ(*future.result(), kSimpleTestFile.size()); + std::vector buffer(kSimpleTestFile.size()); FILE* file = fopen(path.c_str(), "rb"); EXPECT_NE(file, nullptr); diff --git a/storage/src/ios/storage_reference_ios.mm b/storage/src/ios/storage_reference_ios.mm index d2260e3416..6f6c139fd2 100644 --- a/storage/src/ios/storage_reference_ios.mm +++ b/storage/src/ios/storage_reference_ios.mm @@ -142,7 +142,25 @@ // Cache a copy of the impl and storage, in case this is destroyed before the thread runs. FIRStorageReference* my_impl = impl(); StorageInternal* storage = storage_; - NSURL* local_file_url = [NSURL URLWithString:@(path)]; + NSString* path_string = @(path); + if (path_string.length == 0) { + future_impl->Complete(handle, kErrorUnknown, "Path cannot be empty."); + return GetFileLastResult(); + } + NSURL* local_file_url = nil; + if ([path_string hasPrefix:@"file://"]) { + // If it starts with the prefix, load it assuming a URL string. + local_file_url = [NSURL URLWithString:path_string]; + } else { + // Otherwise, assume it is a file path. + local_file_url = [NSURL fileURLWithPath:path_string]; + } + // If we still failed to convert the path, error out. + if (local_file_url == nil) { + future_impl->Complete(handle, kErrorUnknown, + "Unable to convert provided path to valid URL"); + return GetFileLastResult(); + } util::DispatchAsyncSafeMainQueue(^() { FIRStorageDownloadTask *download_task; {