This package aims to be a dart SDK for the Cloudflare API. It uses retrofit for REST requests and tusc for pause/resume uploads using tus protocol.
API | Available |
---|---|
Cloudflare Images | âś… |
Stream Videos | âś… |
Stream Live Inputs | âś… |
- Installation
- How to use
- Final notes
The first thing is to add cloudflare as a dependency of your project, for this you can use the command:
For purely Dart projects
dart pub add cloudflare
For Flutter projects
flutter pub add cloudflare
This command will add cloudflare to the pubspec.yaml of your project. Finally you just have to run:
dart pub get
or flutter pub get
depending on the project type and this will download the dependency to your pub-cache
For server side apps where you can securely store accountId
, token
or any cloudflare credential, you can use the full Cloudflare
constructor.
cloudflare = Cloudflare(
apiUrl: apiUrl,
accountId: accountId,
token: token,
apiKey: apiKey,
accountEmail: accountEmail,
userServiceKey: userServiceKey,
timeout: timeout,
httpClient: httpClient,
);
apiUrl
: Optional. This is the base url for Cloudflare APIs, at the time of writing this, the url is: https://api.cloudflare.com/client/v4, which is used by default.
accountId
: Required. The accountId that identifies your Cloudflare account, you can find this id on your Developer Resources at your Cloudflare Dash or simply copying from the url when you select the account at Cloudflare Dash; something like https://dash.cloudflare.com/xxxxxxxxxxxxxxx/images/images.
token
: Optional. The API Token provide a new way to authenticate with the Cloudflare API. It allows for scoped and permissioned access to resources. This token can be generated from User Profile 'API Tokens' page
apiKey
: Optional. API key generated on the "My Account" page
accountEmail
: Optional. Email address associated with your account
userServiceKey
: Optional. A special Cloudflare API key good for a restricted set of endpoints. Always begins with "v1.0-", may vary in length.
timeout
: Optional. The duration to wait until an api request should timeout.
httpClient
: Optional. Set this if you need control over http requests like validating certificates and so. Not supported in Web.
For authorized requests to Cloudflare API you just need a token
or apiKey/accountEmail
or userServiceKey
not all. Cloudflare's recommended authorization way is to use token
authorization. So a valid Cloudflare full access api instance could be as simple as:
cloudflare = Cloudflare(
accountId: accountId,
token: token,
);
If for some reason you need to use old API keys you can also use this valid Cloudflare instances:
cloudflare = Cloudflare(
accountId: accountId,
apiKey: apiKey,
accountEmail: accountEmail,
);
or
cloudflare = Cloudflare(
accountId: accountId,
userServiceKey: userServiceKey,
);
For client side apps like flutter apps where you can't securely store accountId
, token
or any cloudflare credential, like when you just need to do image or stream direct upload, it's recommended to use the .basic()
constructor.
cloudflare = Cloudflare.basic(apiUrl: apiUrl); //apiUrl is optional
await cloudflare.init();
Done, you can now access Cloudflare API.
CloudflareHTTPResponse
: Contains the HTTP response from a network call to a Cloudflare API endpoint.CloudflareResponse
: It's the body content of aCloudflareHTTPResponse
. Check hereCloudflareErrorResponse
: It's the content of the error of aCloudflareHTTPResponse
. Also check hereCloudflareImage
: It's the representation of Cloudflare Image data. Check here and hereCloudflareStreamVideo
: It's the representation of Stream Video data. Check here and hereCloudflareLiveInput
: It's the representation of Stream Live Input data. Check here and hereDataTransmit
: It's the representation of the data that will be uploaded to Cloudflare, data could be aFile
, aString
file path, or a byte arrayList<Uint8List>
. This class allows you to listen for data transmit progress, by using itsprogressCallback
and also allows you to cancel a data transmit ongoing request by using thecancelToken
.
You can upload an image from file, file path or directly from it's binary representation as a byte array. Official documentation here
//From file
CloudflareHTTPResponse<CloudflareImage?> responseFromFile = await cloudflare.imageAPI.upload(
contentFromFile: DataTransmit<File>(data: imageFile, progressCallback: (count, total) {
print('Upload progress: $count/$total');
})
);
//From path
CloudflareHTTPResponse<CloudflareImage?> responseFromPath = await cloudflare.imageAPI.upload(
contentFromPath: DataTransmit<String>(data: imagePath, progressCallback: (count, total) {
print('Upload progress: $count/$total');
})
);
//From bytes
CloudflareHTTPResponse<CloudflareImage?> responseFromBytes = await cloudflare.imageAPI.upload(
contentFromBytes: DataTransmit<Uint8List>(data: imageBytes, progressCallback: (count, total) {
print('Upload progress: $count/$total');
})
);
Just like you upload an image you can also upload multiple images from files, file paths or byte arrays.
//From files
List<CloudflareHTTPResponse<CloudflareImage?>> responseFromFiles = await cloudflare.imageAPI.uploadMultiple(contentFromFiles: contentFromFiles);
//From paths
List<CloudflareHTTPResponse<CloudflareImage?>> responseFromPaths = await cloudflare.imageAPI.uploadMultiple(contentFromPaths: contentFromPaths);
//From bytes
List<CloudflareHTTPResponse<CloudflareImage?>> responseFromBytes = await cloudflare.imageAPI.uploadMultiple(contentFromBytes: contentFromBytes);
Creates a draft record for a future image and returns upload URL and image identifier that can be used later to verify if image itself has been uploaded or not with the draft: true property in the image response. This request is used to allow client side apps to later direct upload an image without API key or token. Official documentation here
final response = await cloudflare.imageAPI.createDirectUpload();
final dataUploadDraft = response.body;
print(dataUploadDraft?.id);
print(dataUploadDraft?.uploadURL);
For image direct upload without API key or token. This function is to be used specifically after an image createDirectUpload
has been requested. A common place to use this is in client side apps.
Official documentation here
final response = await cloudflare.imageAPI.directUpload(
dataUploadDraft: dataUploadDraft!,
contentFromFile: DataTransmit<File>(
data: imageFile,
progressCallback: (count, total) {
print('Image upload to direct upload URL from file: $count/$total');
})
);
Up to 100 images can be listed with one request, use optional parameters to get a specific range of images. Official documentation here
CloudflareHTTPResponse<List<CloudflareImage>?> responseList = await cloudflare.imageAPI.getAll(page: 1, size: 20);
Fetch details of a single image.
This way you get the CloudflareImage
object.
Official documentation here
CloudflareHTTPResponse<CloudflareImage> response = await cloudflare.imageAPI.get(id: imageId);
This way you get the binary from the originally uploaded image: Official documentation here
CloudflareHTTPResponse<List<int>?> response = await cloudflare.imageAPI.getBase(id: imageId!);
Update image access control. On access control change, all copies of the image are purged from Cache. Official documentation here
final response = await cloudflare.imageAPI.update(
image: CloudflareImage(
id: imageId!,
requireSignedURLs: false,
meta: metadata,
)
);
Fetch details of Cloudflare Images usage statistics. Official documentation here
final CloudflareHTTPResponse<ImageStats?> response = await cloudflare.imageAPI.getStats();
Delete an image on Cloudflare Images. On success, all copies of the image are deleted and purged from Cache. Official documentation here
final response = await cloudflare.imageAPI.delete(id: imageId);
Delete a list of images on Cloudflare Images. On success, all copies of the images are deleted and purged from Cache.
final responses = await cloudflare.imageAPI.deleteMultiple(ids: idList);
for (final response in responses) {
print(response.isSuccessful);
}
A video up to 200 MegaBytes can be uploaded using a single HTTP POST (multipart/form-data) request. For larger file sizes, please upload using the TUS protocol. You can upload a video from url, file, file path or directly from it’s binary representation as a byte array Official documentation here and here
//From url
CloudflareHTTPResponse<CloudflareStreamVideo?> response = await cloudflare.streamAPI.stream(
contentFromUrl: DataTransmit<String>(
data: videoUrl,
progressCallback: (count, total) {
print('Stream video progress: $count/$total');
}
)
);
//From file
CloudflareHTTPResponse<CloudflareStreamVideo?> response = await cloudflare.streamAPI.stream(
contentFromFile: DataTransmit<File>(
data: videoFile,
progressCallback: (count, total) {
print('Stream video progress: $count/$total');
}
)
);
//From path
CloudflareHTTPResponse<CloudflareStreamVideo?> response = await cloudflare.streamAPI.stream(
contentFromFile: DataTransmit<String>(
data: videoFile.path,
progressCallback: (count, total) {
print('Stream video progress: $count/$total');
}
)
);
//From bytes
CloudflareHTTPResponse<CloudflareStreamVideo?> response = await cloudflare.streamAPI.stream(
contentFromFile: DataTransmit<Uint8List>(
data: videoFile.readAsBytesSync(),
progressCallback: (count, total) {
print('Stream video progress: $count/$total');
}
)
);
Just like you do a stream upload you can also do multiple stream upload from urls, files, file paths or byte arrays.
//From urls
List<CloudflareHTTPResponse<CloudflareStreamVideo?>> responseFromUrls = await cloudflare.streamAPI.streamMultiple(contentFromUrls: contentFromUrls);
//From files
List<CloudflareHTTPResponse<CloudflareStreamVideo?>> responseFromFiles = await cloudflare.streamAPI.streamMultiple(contentFromFiles: contentFromFiles);
//From paths
List<CloudflareHTTPResponse<CloudflareStreamVideo?>> responseFromPaths = await cloudflare.streamAPI.streamMultiple(contentFromPaths: contentFromPaths);
//From bytes
List<CloudflareHTTPResponse<CloudflareImageCloudflareStreamVideo?>> responseFromBytes = await cloudflare.streamAPI.streamMultiple(contentFromBytes: contentFromBytes);
Direct uploads allow users to upload videos without API keys. A common place to use direct uploads is on web apps, client side applications, or on mobile devices where users upload content directly to Stream. This request is used to allow client side apps to later direct stream upload a video without API key or token.
Direct uploads occupy minutes of videos on your Stream account until they are expired. A maxDurationSeconds
value is required to calculate the duration the video will occupy before the video is uploaded. After upload, the duration of the uploaded will be used instead. If a video longer than this value is uploaded, the video will result in an error.
Min value: 1 second
Max value: 21600 seconds which is 360 mins, 6 hours
e.g: 300 seconds which is 5 mins
Official documentation here
final response = await cloudflare.imageAPI.createDirectStreamUpload(maxDurationSeconds: 60);
final dataUploadDraft = response.body;
print(dataUploadDraft?.id);
print(dataUploadDraft?.uploadURL);
For video direct stream upload without API key or token. This function is to be used specifically after a video createDirectStreamUpload
has been requested. A common place to use this is in client side apps.
A video up to 200 MegaBytes can be uploaded using a single HTTP POST (multipart/form-data) request. For larger file sizes, please upload using the TUS protocol. Official documentation here
final response = await cloudflare.imageAPI.directStreamUpload(
dataUploadDraft: dataUploadDraft!,
contentFromFile: DataTransmit<File>(
data: imageFile,
progressCallback: (count, total) {
print('Stream video to direct upload URL from file: $count/$total');
})
);
For videos larger than 200 MegaBytes tus protocol is used. tus protocol also allows you to pause/resume uploads. Similar to the normal stream upload described above you can also stream upload from a file, file path or byte array using tus protocol Official documentation here
final tusAPI = await cloudflare.streamAPI.tusStream(
file: videoFile,
name: 'test-video-upload',
cache: TusMemoryCache()
);
tusAPI?.startUpload(
onProgress: (count, total) {
print('tus stream video: $count/$total');
},
onComplete: (cloudflareStreamVideo) {
print('tus stream video completed');
},
onTimeout: () {
print('tus request timeout');
}
);
await Future.delayed(const Duration(seconds: 2), () {
print('Upload paused');
tusAPI.pauseUpload();
});
await Future.delayed(const Duration(seconds: 4), () {
print('Upload resumed');
tusAPI.resumeUpload();
});
Direct upload using tus(https://tus.io) protocol. Direct uploads allow users to upload videos without API keys. A common place to use direct uploads is on web apps, client side applications, or on mobile devices where users upload content directly to Stream.
IMPORTANT: when using tus protocol for direct stream upload it's not required to set a maxDurationSeconds
because Cloudflare will reserve a loose amount o minutes for the video to be uploaded, for instance 240 minutes will be reserved from your available storage. Nevertheless it's recommended to set the maxDurationSeconds
to avoid running out of available minutes when multiple simultaneously tus uploads are taking place.
It's required to set the size
of the file to upload.
Direct uploads occupy minutes of videos on your Stream account until they are expired. A maxDurationSeconds
value is used to calculate the duration the video will occupy before the video is uploaded. After upload, the duration of the uploaded will be used instead. If a video longer than this value is uploaded, the video will result in an error.
Min value: 1 second
Max value: 21600 seconds which is 360 mins, 6 hours
e.g: 300 seconds which is 5 mins
Official documentation here
final response = await cloudflare.imageAPI.createTusDirectStreamUpload(
size: File(dataVideo!.dataTransmit.data).lengthSync(),
maxDurationSeconds: videoPlayerController.value.duration.inSeconds,
name: 'tus-video-direct-upload',
);
final dataUploadDraft = response.body;
print(dataUploadDraft?.id);
print(dataUploadDraft?.uploadURL);
For larger than 200 MegaBytes video direct stream upload using tus protocol without API key or token. This function is to be used specifically after a video createTusDirectStreamUpload
has been requested. A common place to use this is in client side apps.
final tusAPI = await cloudflare.streamAPI.tusDirectStreamUpload(
dataUploadDraft: dataUploadDraft!,
file: videoFile,
cache: TusPersistentCache(''),
);
tusAPI?.startUpload(
onProgress: (count, total) {
print('tus stream video: $count/$total');
},
onComplete: (cloudflareStreamVideo) {
print('tus stream video completed');
},
onTimeout: () {
print('tus request timeout');
}
);
await Future.delayed(const Duration(seconds: 2), () {
print('Upload paused');
tusAPI.pauseUpload();
});
await Future.delayed(const Duration(seconds: 4), () {
print('Upload resumed');
tusAPI.resumeUpload();
});
This package uses the tusc package implementation, which brings two kinds of cache, TusMemoryCache
which allows you to pause/resume uploads as long as app keeps running and TusPersistentCache
which allows you to pause/resume uploads no matter if app closes or even device gets restarted.
Up to 1000 videos can be listed with one request, use optional parameters to get a specific range of videos. Please note that Cloudflare Stream does not use pagination, instead it uses a cursor pattern to list more than 1000 videos. In order to list all videos, make multiple requests to the API using the created date-time of the last item in the previous request as the before or after parameter. Official documentation here
CloudflareHTTPResponse<List<CloudflareStreamVideo>?> responseList = await cloudflare.streamAPI.getAll(
search: 'puppy.mp4',
before: DateTime.now(),
limit: 20,
);
Fetch details of a single video. Official documentation here
CloudflareHTTPResponse<CloudflareImage> response = await cloudflare.streamAPI.get(id: videoId);
Delete a video on Cloudflare Stream. On success, all copies of the video are deleted. Official documentation here
final response = await cloudflare.streamAPI.delete(video: cloudflareStreamVideo,);
Deletes a list of videos on Cloudflare Stream. On success, all copies of the videos are deleted.
final responses = await cloudflare.streamAPI.deleteMultiple(ids: idList);
for (final response in responses) {
print(response.isSuccessful);
}
Creates a live input that can be streamed to. Official documentation here
final response = await cloudflare.liveInputAPI.create(
data: CloudflareLiveInput(
meta: {
Params.name: 'live input test name'
},
recording: LiveInputRecording(
mode: LiveInputRecordingMode.automatic,
allowedOrigins: ['example.com'],
timeoutSeconds: 4,
requireSignedURLs: true,
)
)
);
View the live inputs that have been created. Some information is not included on list requests, such as the URL to stream to. To get that information, request a single live input. Official documentation here
final responseList = await cloudflare.liveInputAPI.getAll();
Fetch details about a single live input Official documentation here
final response = await cloudflare.liveInputAPI.get(id: liveInputId!);
Get theCloudflareStreamVideo
list associated to a CloudflareLiveInput
Official documentation here
final responseList = await cloudflare.liveInputAPI.getVideos(id: liveInputId!);
Update details about a single live input Official documentation here
final response = await cloudflare.liveInputAPI.update(
liveInput: CloudflareLiveInput(
id: liveInputId,
meta: metadata,
recording: recording,
)
);
Prevent a live input from being streamed to. This makes the live input inaccessible to any future API calls or RTMPS transmission. Official documentation here
final response = await cloudflare.liveInputAPI.delete(id: liveInputId);
Deletes a list of live inputs on Cloudflare LiveInput. On success, all copies of the live inputs are deleted.
final responses = await cloudflare.liveInputAPI.deleteMultiple(ids: idList);
for (final response in responses) {
print(response.isSuccessful);
}
Creates a new output which will be re-streamed to by a live input Official documentation here
final response = await cloudflare.liveInputAPI.addOutput(
liveInputId: liveInputId,
data: LiveInputOutput(
url: 'rtmp://a.rtmp.youtube.com/live2',
streamKey: 'uzya-f19y-g2g9-a2ee-51j2'
)
);
List outputs associated with a live input Official documentation here
final responseList = await cloudflare.liveInputAPI.getOutputs(liveInputId: liveInputId);
Removes an output from a live input Official documentation here
final response = await removeOutput(
liveInputId: liveInputId,
outputId: outputId,
);
Removes a list of outputs associated to a LiveInput
final responses = await cloudflare.liveInputAPI.removeMultipleOutputs(
liveInputId: liveInputId,
outputs: outputs,
);
- Every class, property and function is documented and references Cloudfare's official documentation.
- Check the example project to see how to use this package from a flutter app.
- Check the unit tests to see how to use each api in details.