mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-16 00:34:19 +00:00
URL: Allow specifying shared container for downloads on iOS
This commit is contained in:
parent
fb09a97be4
commit
f87582a013
7 changed files with 110 additions and 52 deletions
|
|
@ -554,9 +554,9 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
|
||||
};
|
||||
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost)
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options)
|
||||
{
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost);
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -648,9 +648,9 @@ public:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
|
||||
};
|
||||
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost)
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options)
|
||||
{
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost);
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options);
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -607,9 +607,9 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
|
||||
};
|
||||
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost)
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options)
|
||||
{
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost);
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -412,10 +412,8 @@ struct BackgroundDownloadTask : public URL::DownloadTask
|
|||
{
|
||||
BackgroundDownloadTask (const URL& urlToUse,
|
||||
const File& targetLocationToUse,
|
||||
String extraHeadersToUse,
|
||||
URL::DownloadTask::Listener* listenerToUse,
|
||||
bool shouldUsePostRequest)
|
||||
: listener (listenerToUse),
|
||||
const URL::DownloadTaskOptions& options)
|
||||
: listener (options.listener),
|
||||
uniqueIdentifier (String (urlToUse.toString (true).hashCode64()) + String (Random().nextInt64()))
|
||||
{
|
||||
targetLocation = targetLocationToUse;
|
||||
|
|
@ -429,11 +427,11 @@ struct BackgroundDownloadTask : public URL::DownloadTask
|
|||
auto nsUrl = [NSURL URLWithString: juceStringToNS (urlToUse.toString (true))];
|
||||
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL: nsUrl];
|
||||
|
||||
if (shouldUsePostRequest)
|
||||
if (options.usePost)
|
||||
[request setHTTPMethod: @"POST"];
|
||||
|
||||
StringArray headerLines;
|
||||
headerLines.addLines (extraHeadersToUse);
|
||||
headerLines.addLines (options.extraHeaders);
|
||||
headerLines.removeEmptyStrings (true);
|
||||
|
||||
for (int i = 0; i < headerLines.size(); ++i)
|
||||
|
|
@ -445,10 +443,14 @@ struct BackgroundDownloadTask : public URL::DownloadTask
|
|||
[request addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)];
|
||||
}
|
||||
|
||||
session =
|
||||
[NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: juceStringToNS (uniqueIdentifier)]
|
||||
delegate: delegate
|
||||
delegateQueue: nullptr];
|
||||
auto* configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: juceStringToNS (uniqueIdentifier)];
|
||||
|
||||
if (options.sharedContainer.isNotEmpty())
|
||||
[configuration setSharedContainerIdentifier: juceStringToNS (options.sharedContainer)];
|
||||
|
||||
session = [NSURLSession sessionWithConfiguration: configuration
|
||||
delegate: delegate
|
||||
delegateQueue: nullptr];
|
||||
|
||||
if (session != nullptr)
|
||||
downloadTask = [session downloadTaskWithRequest:request];
|
||||
|
|
@ -648,9 +650,9 @@ struct BackgroundDownloadTask : public URL::DownloadTask
|
|||
|
||||
HashMap<String, BackgroundDownloadTask*, DefaultHashFunctions, CriticalSection> BackgroundDownloadTask::activeSessions;
|
||||
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool usePostRequest)
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options)
|
||||
{
|
||||
std::unique_ptr<BackgroundDownloadTask> downloadTask (new BackgroundDownloadTask (*this, targetLocation, extraHeaders, listener, usePostRequest));
|
||||
auto downloadTask = std::make_unique<BackgroundDownloadTask> (*this, targetLocation, options);
|
||||
|
||||
if (downloadTask->initOK() && downloadTask->connect())
|
||||
return downloadTask;
|
||||
|
|
@ -663,9 +665,9 @@ void URL::DownloadTask::juce_iosURLSessionNotify (const String& identifier)
|
|||
BackgroundDownloadTask::invokeNotify (identifier);
|
||||
}
|
||||
#else
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool usePost)
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options)
|
||||
{
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, usePost);
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -929,9 +931,9 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (URLConnectionState)
|
||||
};
|
||||
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost)
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options)
|
||||
{
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost);
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options);
|
||||
}
|
||||
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
|
|
|||
|
|
@ -650,9 +650,9 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailA
|
|||
return mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS;
|
||||
}
|
||||
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost)
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options)
|
||||
{
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost);
|
||||
return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options);
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -106,29 +106,26 @@ struct FallbackDownloadTask : public URL::DownloadTask,
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FallbackDownloadTask)
|
||||
};
|
||||
|
||||
void URL::DownloadTask::Listener::progress (DownloadTask*, int64, int64) {}
|
||||
URL::DownloadTask::Listener::~Listener() {}
|
||||
void URL::DownloadTaskListener::progress (DownloadTask*, int64, int64) {}
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<URL::DownloadTask> URL::DownloadTask::createFallbackDownloader (const URL& urlToUse,
|
||||
const File& targetFileToUse,
|
||||
const String& extraHeadersToUse,
|
||||
Listener* listenerToUse,
|
||||
bool usePostRequest)
|
||||
const DownloadTaskOptions& options)
|
||||
{
|
||||
const size_t bufferSize = 0x8000;
|
||||
targetFileToUse.deleteFile();
|
||||
|
||||
if (auto outputStream = targetFileToUse.createOutputStream (bufferSize))
|
||||
{
|
||||
auto stream = std::make_unique<WebInputStream> (urlToUse, usePostRequest);
|
||||
stream->withExtraHeaders (extraHeadersToUse);
|
||||
auto stream = std::make_unique<WebInputStream> (urlToUse, options.usePost);
|
||||
stream->withExtraHeaders (options.extraHeaders);
|
||||
|
||||
if (stream->connect (nullptr))
|
||||
return std::make_unique<FallbackDownloadTask> (std::move (outputStream),
|
||||
bufferSize,
|
||||
std::move (stream),
|
||||
listenerToUse);
|
||||
options.listener);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
@ -1005,4 +1002,15 @@ std::unique_ptr<InputStream> URL::createInputStream (bool usePostCommand,
|
|||
.withHttpRequestCmd (httpRequestCmd));
|
||||
}
|
||||
|
||||
std::unique_ptr<URL::DownloadTask> URL::downloadToFile (const File& targetLocation,
|
||||
String extraHeaders,
|
||||
DownloadTask::Listener* listener,
|
||||
bool usePostCommand)
|
||||
{
|
||||
auto options = DownloadTaskOptions().withExtraHeaders (std::move (extraHeaders))
|
||||
.withListener (listener)
|
||||
.withUsePost (usePostCommand);
|
||||
return downloadToFile (targetLocation, std::move (options));
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -428,6 +428,64 @@ public:
|
|||
std::unique_ptr<OutputStream> createOutputStream() const;
|
||||
|
||||
//==============================================================================
|
||||
class DownloadTask;
|
||||
|
||||
/** Used to receive callbacks for download progress. */
|
||||
struct JUCE_API DownloadTaskListener
|
||||
{
|
||||
virtual ~DownloadTaskListener() = default;
|
||||
|
||||
/** Called when the download has finished. Be aware that this callback may
|
||||
come on an arbitrary thread.
|
||||
*/
|
||||
virtual void finished (DownloadTask* task, bool success) = 0;
|
||||
|
||||
/** Called periodically by the OS to indicate download progress.
|
||||
|
||||
Beware that this callback may come on an arbitrary thread.
|
||||
*/
|
||||
virtual void progress (DownloadTask* task, int64 bytesDownloaded, int64 totalLength);
|
||||
};
|
||||
|
||||
/** Holds options that will can be specified when starting a new download
|
||||
with downloadToFile().
|
||||
*/
|
||||
class DownloadTaskOptions
|
||||
{
|
||||
public:
|
||||
String extraHeaders;
|
||||
String sharedContainer;
|
||||
DownloadTaskListener* listener = nullptr;
|
||||
bool usePost = false;
|
||||
|
||||
/** Specifies headers to add to the request. */
|
||||
auto withExtraHeaders (String value) const { return with (&DownloadTaskOptions::extraHeaders, std::move (value)); }
|
||||
|
||||
/** On iOS, specifies the container where the downloaded file will be stored.
|
||||
|
||||
If you initiate a download task from inside an app extension on iOS,
|
||||
you must supply this option.
|
||||
|
||||
This is currently unused on other platforms.
|
||||
*/
|
||||
auto withSharedContainer (String value) const { return with (&DownloadTaskOptions::sharedContainer, std::move (value)); }
|
||||
|
||||
/** Specifies an observer for the download task. */
|
||||
auto withListener (DownloadTaskListener* value) const { return with (&DownloadTaskOptions::listener, std::move (value)); }
|
||||
|
||||
/** Specifies whether a post command should be used. */
|
||||
auto withUsePost (bool value) const { return with (&DownloadTaskOptions::usePost, value); }
|
||||
|
||||
private:
|
||||
template <typename Member, typename Value>
|
||||
DownloadTaskOptions with (Member&& member, Value&& value) const
|
||||
{
|
||||
auto copy = *this;
|
||||
copy.*member = std::forward<Value> (value);
|
||||
return copy;
|
||||
}
|
||||
};
|
||||
|
||||
/** Represents a download task.
|
||||
|
||||
Returned by downloadToFile() to allow querying and controlling the download task.
|
||||
|
|
@ -435,22 +493,7 @@ public:
|
|||
class JUCE_API DownloadTask
|
||||
{
|
||||
public:
|
||||
/** Used to receive callbacks for download progress. */
|
||||
struct JUCE_API Listener
|
||||
{
|
||||
virtual ~Listener();
|
||||
|
||||
/** Called when the download has finished. Be aware that this callback may
|
||||
come on an arbitrary thread.
|
||||
*/
|
||||
virtual void finished (URL::DownloadTask* task, bool success) = 0;
|
||||
|
||||
/** Called periodically by the OS to indicate download progress.
|
||||
|
||||
Beware that this callback may come on an arbitrary thread.
|
||||
*/
|
||||
virtual void progress (URL::DownloadTask* task, int64 bytesDownloaded, int64 totalLength);
|
||||
};
|
||||
using Listener = DownloadTaskListener;
|
||||
|
||||
/** Releases the resources of the download task, unregisters the listener
|
||||
and cancels the download if necessary.
|
||||
|
|
@ -493,7 +536,7 @@ public:
|
|||
|
||||
private:
|
||||
friend class URL;
|
||||
static std::unique_ptr<DownloadTask> createFallbackDownloader (const URL&, const File&, const String&, Listener*, bool);
|
||||
static std::unique_ptr<DownloadTask> createFallbackDownloader (const URL&, const File&, const DownloadTaskOptions&);
|
||||
|
||||
public:
|
||||
#if JUCE_IOS
|
||||
|
|
@ -505,6 +548,13 @@ public:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadTask)
|
||||
};
|
||||
|
||||
/** This function is replaced by a new overload accepting a DownloadTaskOptions argument. */
|
||||
[[deprecated ("Use the overload with a DownloadTaskOptions argument instead")]]
|
||||
std::unique_ptr<DownloadTask> downloadToFile (const File& targetLocation,
|
||||
String extraHeaders = String(),
|
||||
DownloadTaskListener* listener = nullptr,
|
||||
bool usePostCommand = false);
|
||||
|
||||
/** Download the URL to a file.
|
||||
|
||||
This method attempts to download the URL to a given file location.
|
||||
|
|
@ -515,9 +565,7 @@ public:
|
|||
network re-connections and continuing your download while your app is suspended.
|
||||
*/
|
||||
std::unique_ptr<DownloadTask> downloadToFile (const File& targetLocation,
|
||||
String extraHeaders = String(),
|
||||
DownloadTask::Listener* listener = nullptr,
|
||||
bool usePostCommand = false);
|
||||
const DownloadTaskOptions& options);
|
||||
|
||||
//==============================================================================
|
||||
/** Tries to download the entire contents of this URL into a binary data block.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue