Skip to content

Commit 2b5850f

Browse files
committed
clod storage post added
1 parent e51d3a4 commit 2b5850f

File tree

5 files changed

+168
-0
lines changed

5 files changed

+168
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
layout: post
3+
title: "Cloud Storage"
4+
date: 2019-04-01
5+
categories: ["Firebase"]
6+
image: firebase/cloud_storage
7+
github: firebase/tree/master/cloud_storage
8+
description: "Firebase"
9+
version: Firebase-Storage 16.0
10+
keywords: "firebase, chmura, dane, pliki, cloud, storage, files, reference, storagereference, task, pobieranie, wysylanie, usuwanie, upload, download, delete, metadata, android, programowanie, programming"
11+
---
12+
13+
## Wprowadzenie
14+
`Cloud Storage` jest wydajną, skalowalną i prostą usługą przechowywania plików aplikacji i użytkowników w chmurze (obrazy, audio, wideo itp). Niezależnie od jakości połączenia sieci pobieranie i przesyłanie jest niezawodne nawet w przypadku utraty połączenia, ponieważ wznawia się w miejscu zatrzymania co pozwala zaoszczędzić czas i przepustowość użytkowników. Operacje w Cloud Storage wykonywane są z zachowaniem reguł bezpieczeństwa i prywatności oraz mogą być integrowane z uwierzytelnianiem `Firebase Authentication`. Pliki przechowywane są w segmencie Google Cloud Storage dzięki czemu dostępne są zarówno w `Firebase` jak i `Google Cloud` co umożliwia przetwarzanie przesłanych plików przez użytkowników po stronie serwera. Dodatkowo istnieje możliwość rozszerzenia Cloud Storage o usługę `Cloud Functions`, czyli uruchamianie funkcji w odpowiedzi na przechwycone zdarzenia z Cloud Storage.
15+
16+
![Pliki](/assets/img/diagrams/firebase/storage_files.png){: .center-image }
17+
18+
## Referencje
19+
Deklaratywny język reguł pozwala określić sposób w jaki dane są indeksowane, strukturyzowane oraz zdefiniować poziom dostępu. Domyślnie dostęp do odczytu i zapisu przyznany jest tylko dla uwierzytelnionych użytkowników. Reguła publicznego dostępu umożliwia dostęp do zasobów nie tylko użytkownikom aplikacji, ale nawet wszystkim którzy z niej nie korzystają. Cloud Storage pozwala na dodatkowe skonfigurowanie przestrzeni ze względu na rejon geograficzny, przeznaczenie zasobów czy też ich współdzielenie.
20+
21+
{% highlight kotlin %}
22+
private fun getStorages() {
23+
val storage = FirebaseStorage.getInstance() //just get FirebaseStorage instance
24+
val customStorage = FirebaseStorage.getInstance("gs://custom-bucket")
25+
}
26+
{% endhighlight %}
27+
28+
Podobnie jak system plików na dysku twardym pliki w Cloud Storage przedstawione są w strukturze hierarchicznej do których dostęp odbywa się poprzez utworzenie referencji metodą `getReference`. Innymi słowy referencja może być traktowana jako wsaźnik do pliku w chmurze. Nawigacja po poziomach struktury plików odbywa się przy użyciu metod `getChild`, `getParent`, `getRoot`.
29+
30+
{% highlight kotlin %}
31+
private fun getReferences(storage: StorageReference) {
32+
val storageRef = storage.reference
33+
val folderRef: StorageReference? = storageRef.child("images")
34+
35+
val fileRef = storageRef.child("images/file.jpg")
36+
val parentRef = fileRef.parent //equivalent of folderRef
37+
val rootRef = fileRef.root //equivalent of storageRef
38+
val anotherFileRef = fileRef.parent?.child("anotherFile.png") //chain navigation together
39+
}
40+
{% endhighlight %}
41+
42+
Każda referencja posiada właściwości opisujące plik takie jak m.in. ścieżka, nazwa, przestrzeń czy metadane.
43+
44+
{% highlight kotlin %}
45+
private fun getInfo(fileRef: StorageReference) {
46+
val info = "$fileRef.name in $fileRef.path in $fileRef.bucket bucket"
47+
val metadata = fileRef.metadata
48+
}
49+
{% endhighlight %}
50+
51+
## Operacje
52+
Wszystkie operacje na plikach, tzn. wysyłanie, pobieranie, usuwanie i zmiana metadanych odnoszą się do instancji `StorageReference` i mogą być wykonane dla dowolnej lokalizacji za wyjątkiem nadrzędnego `root`. Wysyłanie plików przeprowadza się za pomocą metod `putFile`, `putBytes`, `putStream`, pobieranie następuje przy użyciu metod `getFile`, `getBytes`, `getStream`, usuwanie zachodzi przy wykorzystaniu metody `delete`, a aktualizacja metadanych metodą `updateMetadata`.
53+
54+
{% highlight kotlin %}
55+
private fun startUploadFile() {
56+
//get file and create reference
57+
val storageRef = FirebaseStorage.getInstance().reference
58+
val file = Uri.fromFile(File("path/file.jpg"))
59+
val fileRef = storageRef.child("images/${file.lastPathSegment}")
60+
61+
//create custom metadata if needed
62+
val metadata = StorageMetadata.Builder().setContentType("image/jpg").build()
63+
64+
//upload file
65+
val uploadTask = fileRef.putFile(file)
66+
//or fileRef.putFile(file, metadata) for using custom metadata
67+
}
68+
69+
private fun startDownloadFile() {
70+
val storageRef = FirebaseStorage.getInstance().reference
71+
val file = File.createTempFile("images", "jpg")
72+
val fileRef = storageRef.child("images/file.jpg")
73+
val downloadTask = fileRef.getFile(file)
74+
}
75+
76+
private fun startDeleteFile() {
77+
val storageRef = FirebaseStorage.getInstance().reference
78+
val fileRef = storageRef.child("images/file.jpg")
79+
val deleteTask = fileRef.delete()
80+
}
81+
82+
private fun startUpdateMetadata() {
83+
val storageRef = FirebaseStorage.getInstance().reference
84+
val fileRef = storageRef.child("images/file.jpg")
85+
86+
val metadata = StorageMetadata.Builder()
87+
.setContentType("image/jpg")
88+
.setCustomMetadata("myCustomProperty", "myValue")
89+
.build()
90+
91+
val metadataTask = fileRef.updateMetadata(metadata)
92+
}
93+
{% endhighlight %}
94+
95+
## Status
96+
Rozpoczęcie wykonywania zadania zwraca właściwy dla danej operacji obiekt rozszerzający klasę `StorageTask`, który pozwala na zarządzanie i monitorowanie statusu operacji poprzez podpięcie słuchaczy dla różnych stanów, tj. `OnProgressListener`, `OnPausedListener`, `OnSuccessListener`, `OnFailureListener`. Metody `pause`, `resume`, `cancel` umożliwiają manualne zarządzanie statusem zadania. W przypadku zamknięcia procesu aplikacji wszystkie zadania są przerywane. Należy więc zadbać o ich właściwe wznowienie w miejscu przerwania (nie od początku) co pozwoli na oszczędzenie czasu i transmisji danych użytkownika.
97+
98+
{% highlight kotlin %}
99+
override fun onCreate(savedInstanceState: Bundle?) {
100+
super.onCreate(savedInstanceState)
101+
setContentView(R.layout.activity_main)
102+
103+
uploadButton.setOnClickListener { startUploadFileWithListeners() }
104+
cancelButton.setOnClickListener { uploadTask?.cancel() }
105+
106+
//check if upload task has been interrupted
107+
val taskInterrupted = false //mock, get from persistent storage
108+
if(taskInterrupted) {
109+
restartUploadFile()
110+
}
111+
}
112+
113+
private fun startUploadFileWithListeners() {
114+
val storageRef = FirebaseStorage.getInstance().reference
115+
val file = Uri.fromFile(File("path/file.jpg"))
116+
fileRef = storageRef.child("images/${file.lastPathSegment}")
117+
118+
//start and add listeners
119+
uploadTask = fileRef.putFile(file)
120+
uploadTask.addOnProgressListener { taskSnapshot ->
121+
//save session URI in persistent storage in case of process die
122+
val sessionUri = taskSnapshot.uploadSessionUri
123+
//show some progress
124+
}.addOnFailureListener {
125+
//action on error like show message
126+
}.addOnSuccessListener {
127+
//action on success like show file in UI
128+
}
129+
}
130+
131+
private fun restartUploadFile {
132+
val storageRef = FirebaseStorage.getInstance().reference
133+
val file = Uri.fromFile(File("path/file.jpg"))
134+
val sessionUri = Uri.EMPTY //mock value, get from persistent storage
135+
uploadTask = storageRef.putFile(file, StorageMetadata.Builder().build(), sessionUri)
136+
}
137+
138+
//do in the similar way for other operations
139+
{% endhighlight %}
140+
141+
## Cykl życia
142+
Przesyłanie kontynuowane jest w tle niezależnie od zmian cyklu życia `Aktywności` co pomimo niewątpliwej zalety może prowadzić do wycieku pamięci dla dodanych wcześniej obserwatorów. Aby temu zapobiec należy we właściwym miejscu cyklu życia wyrejestrować obiekty słuchaczy, a następnie zarejestrować ponownie pobierając instancje bieżącego zadania za pomocą metody `getActiveUploadTask` lub `getActiveDownloadTask`.
143+
144+
{% highlight kotlin %}
145+
override fun onSaveInstanceState(outState: Bundle) {
146+
super.onSaveInstanceState(outState)
147+
//save the reference to upload task if is in progress
148+
fileRef?.let { outState.putString("reference", it.toString()) }
149+
}
150+
151+
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
152+
super.onRestoreInstanceState(savedInstanceState)
153+
154+
//get reference to upload task if was in progress
155+
val reference = savedInstanceState.getString("reference")
156+
if(reference != null) {
157+
fileRef = FirebaseStorage.getInstance().getReferenceFromUrl(reference)
158+
159+
//get all UploadTask - in this case there should be one
160+
fileRef?.activeUploadTasks?.let { it ->
161+
if (it.size > 0) {
162+
val task = it[0]
163+
//set listeners to task here
164+
}
165+
}
166+
}
167+
}
168+
{% endhighlight %}
20.3 KB
Loading
445 KB
Loading
16.2 KB
Loading
47.5 KB
Loading

0 commit comments

Comments
 (0)