curl -L -X GET "https://api.tktchurch.com/v1/files/provider/s3/download/uploads/abc123.jpg" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
const downloadFile = async (accessToken, provider, key) => {
const response = await fetch(
`https://api.tktchurch.com/v1/files/provider/${provider}/download/${key}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`
},
redirect: 'follow'
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.reason || 'Failed to download file');
}
return response.blob();
};
// Usage
try {
const blob = await downloadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
'uploads/abc123.jpg'
);
// Create download link
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'example.jpg';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
} catch (error) {
console.error('Error:', error.message);
}
func downloadFile(
accessToken: String,
provider: String,
key: String
) async throws -> Data {
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/files/provider/\(provider)/download/\(key)")!)
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
throw URLError(.badServerResponse)
}
return data
}
// Usage
do {
let data = try await downloadFile(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
provider: "s3",
key: "uploads/abc123.jpg"
)
// Save file
let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let filePath = documentsPath.appendingPathComponent("example.jpg")
try data.write(to: filePath)
print("File downloaded to:", filePath)
} catch {
print("Error:", error)
}
suspend fun downloadFile(
accessToken: String,
provider: String,
key: String
): ByteArray {
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/files/provider/$provider/download/$key")
.get()
.header("Authorization", "Bearer $accessToken")
.build()
return withContext(Dispatchers.IO) {
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
throw IOException("Unexpected response ${response.code}")
}
response.body?.bytes() ?: throw IOException("Empty response")
}
}
}
// Usage
try {
val bytes = downloadFile(
"eyJhbGciOiJIUzI1NiIs...",
"s3",
"uploads/abc123.jpg"
)
// Save file
File("example.jpg").writeBytes(bytes)
println("File downloaded successfully")
} catch (e: Exception) {
println("Error: ${e.message}")
}
const downloadFile = async (
accessToken: string,
provider: 's3' | 'local',
key: string
): Promise<Blob> => {
try {
const response = await axios.get(
`https://api.tktchurch.com/v1/files/provider/${provider}/download/${key}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`
},
responseType: 'blob',
maxRedirects: 5
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.reason || 'Failed to download file');
}
throw error;
}
};
// Usage
try {
const blob = await downloadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
'uploads/abc123.jpg'
);
// Save file using react-native-fs
const path = `${RNFS.DocumentDirectoryPath}/example.jpg`;
await RNFS.writeFile(path, blob, 'base64');
console.log('File downloaded to:', path);
} catch (error) {
console.error('Error:', error.message);
}
HTTP/1.1 302 Found
Location: https://storage.example.com/uploads/abc123.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
{
"error": {
"status": 400,
"reason": "Invalid provider specified"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: viewFiles"
}
}
{
"error": {
"status": 404,
"reason": "File not found"
}
}
Files
Download File
Download a file by redirecting to a signed URL
GET
/
files
/
provider
/
{provider}
/
download
/
{key}
curl -L -X GET "https://api.tktchurch.com/v1/files/provider/s3/download/uploads/abc123.jpg" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
const downloadFile = async (accessToken, provider, key) => {
const response = await fetch(
`https://api.tktchurch.com/v1/files/provider/${provider}/download/${key}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`
},
redirect: 'follow'
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.reason || 'Failed to download file');
}
return response.blob();
};
// Usage
try {
const blob = await downloadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
'uploads/abc123.jpg'
);
// Create download link
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'example.jpg';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
} catch (error) {
console.error('Error:', error.message);
}
func downloadFile(
accessToken: String,
provider: String,
key: String
) async throws -> Data {
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/files/provider/\(provider)/download/\(key)")!)
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
throw URLError(.badServerResponse)
}
return data
}
// Usage
do {
let data = try await downloadFile(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
provider: "s3",
key: "uploads/abc123.jpg"
)
// Save file
let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let filePath = documentsPath.appendingPathComponent("example.jpg")
try data.write(to: filePath)
print("File downloaded to:", filePath)
} catch {
print("Error:", error)
}
suspend fun downloadFile(
accessToken: String,
provider: String,
key: String
): ByteArray {
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/files/provider/$provider/download/$key")
.get()
.header("Authorization", "Bearer $accessToken")
.build()
return withContext(Dispatchers.IO) {
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
throw IOException("Unexpected response ${response.code}")
}
response.body?.bytes() ?: throw IOException("Empty response")
}
}
}
// Usage
try {
val bytes = downloadFile(
"eyJhbGciOiJIUzI1NiIs...",
"s3",
"uploads/abc123.jpg"
)
// Save file
File("example.jpg").writeBytes(bytes)
println("File downloaded successfully")
} catch (e: Exception) {
println("Error: ${e.message}")
}
const downloadFile = async (
accessToken: string,
provider: 's3' | 'local',
key: string
): Promise<Blob> => {
try {
const response = await axios.get(
`https://api.tktchurch.com/v1/files/provider/${provider}/download/${key}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`
},
responseType: 'blob',
maxRedirects: 5
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.reason || 'Failed to download file');
}
throw error;
}
};
// Usage
try {
const blob = await downloadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
'uploads/abc123.jpg'
);
// Save file using react-native-fs
const path = `${RNFS.DocumentDirectoryPath}/example.jpg`;
await RNFS.writeFile(path, blob, 'base64');
console.log('File downloaded to:', path);
} catch (error) {
console.error('Error:', error.message);
}
HTTP/1.1 302 Found
Location: https://storage.example.com/uploads/abc123.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
{
"error": {
"status": 400,
"reason": "Invalid provider specified"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: viewFiles"
}
}
{
"error": {
"status": 404,
"reason": "File not found"
}
}
This endpoint requires authentication and the
viewFiles permission.
The endpoint returns a 302 redirect to a signed URL that expires in 5 minutes.Path Parameters
string
required
The storage provider. One of:
s3: Amazon S3 storagelocal: Local file storage
string
required
The storage key/path of the file
Response
Returns HTTP 302 Found with a Location header containing a signed URL for downloading the file.Error Responses
object
Common error cases:
- 400 Bad Request: Invalid provider or key
- 401 Unauthorized: Missing or invalid access token
- 403 Forbidden: Missing required permission
- 404 Not Found: File not found
curl -L -X GET "https://api.tktchurch.com/v1/files/provider/s3/download/uploads/abc123.jpg" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
const downloadFile = async (accessToken, provider, key) => {
const response = await fetch(
`https://api.tktchurch.com/v1/files/provider/${provider}/download/${key}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`
},
redirect: 'follow'
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.reason || 'Failed to download file');
}
return response.blob();
};
// Usage
try {
const blob = await downloadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
'uploads/abc123.jpg'
);
// Create download link
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'example.jpg';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
} catch (error) {
console.error('Error:', error.message);
}
func downloadFile(
accessToken: String,
provider: String,
key: String
) async throws -> Data {
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/files/provider/\(provider)/download/\(key)")!)
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
throw URLError(.badServerResponse)
}
return data
}
// Usage
do {
let data = try await downloadFile(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
provider: "s3",
key: "uploads/abc123.jpg"
)
// Save file
let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let filePath = documentsPath.appendingPathComponent("example.jpg")
try data.write(to: filePath)
print("File downloaded to:", filePath)
} catch {
print("Error:", error)
}
suspend fun downloadFile(
accessToken: String,
provider: String,
key: String
): ByteArray {
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/files/provider/$provider/download/$key")
.get()
.header("Authorization", "Bearer $accessToken")
.build()
return withContext(Dispatchers.IO) {
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
throw IOException("Unexpected response ${response.code}")
}
response.body?.bytes() ?: throw IOException("Empty response")
}
}
}
// Usage
try {
val bytes = downloadFile(
"eyJhbGciOiJIUzI1NiIs...",
"s3",
"uploads/abc123.jpg"
)
// Save file
File("example.jpg").writeBytes(bytes)
println("File downloaded successfully")
} catch (e: Exception) {
println("Error: ${e.message}")
}
const downloadFile = async (
accessToken: string,
provider: 's3' | 'local',
key: string
): Promise<Blob> => {
try {
const response = await axios.get(
`https://api.tktchurch.com/v1/files/provider/${provider}/download/${key}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`
},
responseType: 'blob',
maxRedirects: 5
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.reason || 'Failed to download file');
}
throw error;
}
};
// Usage
try {
const blob = await downloadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
'uploads/abc123.jpg'
);
// Save file using react-native-fs
const path = `${RNFS.DocumentDirectoryPath}/example.jpg`;
await RNFS.writeFile(path, blob, 'base64');
console.log('File downloaded to:', path);
} catch (error) {
console.error('Error:', error.message);
}
HTTP/1.1 302 Found
Location: https://storage.example.com/uploads/abc123.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
{
"error": {
"status": 400,
"reason": "Invalid provider specified"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: viewFiles"
}
}
{
"error": {
"status": 404,
"reason": "File not found"
}
}
