Bermain-main Dengan API Sistem File HTML5
Indonesian (Bahasa Indonesia) translation by Keti Pritania (you can also view the original English article)
HTML5 memberi kita seluruh kemungkinan baru, seperti menggambar dengan kanvas, mengimplementasikan multimedia dengan API audio dan video, dan seterusnya. Salah satu alat ini, yang masih relatif baru, adalah File System API. Ini memberi kami akses ke bagian kotak pasir dari sistem file lokal pengguna, sehingga mengisi kesenjangan antara aplikasi desktop dan web lebih jauh! Dalam tutorial hari ini, kita akan membahas dasar-dasar API baru dan menarik ini, menjelajahi tugas-tugas filesystem yang paling umum. Mari kita mulai!
Pengenalan
Kami tidak lagi perlu mengunduh dan memasang perangkat lunak tertentu untuk menggunakannya. Cukup browser web dan koneksi internet memberi kita kemampuan untuk menggunakan aplikasi web apa pun, kapan saja, di mana saja, dan di platform apa pun.
Singkatnya, aplikasi web itu keren; tetapi, dibandingkan dengan aplikasi desktop, mereka masih memiliki satu kelemahan yang signifikan: mereka tidak memiliki cara untuk berinteraksi dan mengatur data ke dalam hierarki terstruktur folder - sistem file yang nyata. Untungnya, dengan API Filesystem baru, ini dapat diubah. API ini memberi aplikasi web akses terkontrol ke filesystem lokal 'kotak pasir' pribadi, di mana mereka dapat menulis dan membaca file, membuat dan mencantumkan direktori, dan seterusnya. Meskipun pada saat penulisan ini hanya browser Chrome Google yang mendukung implementasi 'penuh' dari Filesystem API, masih layak untuk dipelajari sebagai bentuk penyimpanan lokal yang kuat dan nyaman.
API Filesystem hadir dalam dua versi berbeda. API asynchronous, yang berguna untuk aplikasi normal, dan API sinkron, disediakan untuk digunakan dengan pekerja web. Untuk keperluan tutorial ini, kami secara eksklusif akan mengeksplorasi versi asynchronous dari API.
Langkah 1 - Memulai
Langkah pertama adalah untuk mendapatkan akses ke HTML5 Filesystem dengan meminta sebuah objek LocalFile sistem, metode window.requestFileSystem() global:
1 |
window.requestFileSystem(type, size, successCallback, opt_errorCallback) |
Ada cara untuk aplikasi web untuk "keluar" luar direktori root lokal.
Sebagai dua parameter, Anda menetapkan seumur hidup dan ukuran filesystem yang Anda inginkan. Sebuah filesystem yang terus-menerus ini cocok untuk aplikasi web yang ingin menyimpan data pengguna secara permanen. Browser tidak akan menghapus itu, kecuali permintaan pengguna eksplisit. Sementara filesistem tepat untuk aplikasi web yang ingin untuk cache data, tetapi masih bisa beroperasi jika web browser menghapus filesystem. Ukuran filesystem yang ditentukan dalam bytes dan harus terikat atas wajar pada jumlah data yang Anda perlu untuk menyimpan.
Parameter ketiga merupakan fungsi callback yang dipicu ketika user agent berhasil menyediakan sebuah filesystem. Argumen adalah objek FileSystem. Dan, akhirnya, kita dapat menambahkan fungsi callback opsional, yang disebut ketika terjadi kesalahan, atau permintaan untuk filesistem ditolak. Argumen adalah objek FileError. Meskipun parameter ini opsional, itu adalah selalu ide yang baik untuk menangkap kesalahan untuk pengguna, karena ada beberapa tempat dimana hal-hal yang bisa salah.
Filesystem yang diperoleh dengan fungsi-fungsi ini tergantung pada asal-usul dokumen yang mengandung. Semua dokumen atau aplikasi web dari asal yang sama (host, pelabuhan, dan protokol) berbagi sebuah filesystem. Dua dokumen atau aplikasi dari asal yang berbeda memiliki benar-benar berbeda dan utma filesystem. Sebuah filesystem dibatasi untuk aplikasi tunggal dan tidak dapat mengakses data yang tersimpan di aplikasi lain. Itu juga telah terisolasi dari sisa file pada hard drive pengguna, yang adalah hal yang baik: ada cara untuk aplikasi web untuk "keluar" luar direktori root lokal atau sebaliknya mengakses file yang sewenang-wenang.
Mari kita tinjau sebuah contoh:
1 |
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; |
2 |
|
3 |
window.requestFileSystem(window.TEMPORARY, 5*1024*1024, initFS, errorHandler); |
4 |
|
5 |
function initFS(fs){ |
6 |
alert("Welcome to Filesystem! It's showtime :)"); // Just to check if everything is OK :) |
7 |
// place the functions you will learn bellow here |
8 |
} |
9 |
|
10 |
function errorHandler(){ |
11 |
console.log('An error occured'); |
12 |
} |
Hal ini menciptakan sebuah filesystem sementara dengan 5MB penyimpanan. Kemudian menyediakan fungsi panggilan balik keberhasilan, yang akan kita gunakan untuk mengoperasikan filesystem kami. Dan, tentu saja, handler kesalahan juga ditambahkan - kalau sesuatu yang tidak beres. Di sini, fungsi errorHandler() terlalu generik. Jadi jika Anda ingin, Anda dapat membuat sedikit dioptimalkan versi, yang memberikan pembaca pesan galat yang lebih deskriptif:
1 |
function errorHandler(err){ |
2 |
var msg = 'An error occured: '; |
3 |
|
4 |
switch (err.code) { |
5 |
case FileError.NOT_FOUND_ERR: |
6 |
msg += 'File or directory not found'; |
7 |
break; |
8 |
|
9 |
case FileError.NOT_READABLE_ERR: |
10 |
msg += 'File or directory not readable'; |
11 |
break; |
12 |
|
13 |
case FileError.PATH_EXISTS_ERR: |
14 |
msg += 'File or directory already exists'; |
15 |
break; |
16 |
|
17 |
case FileError.TYPE_MISMATCH_ERR: |
18 |
msg += 'Invalid filetype'; |
19 |
break; |
20 |
|
21 |
default: |
22 |
msg += 'Unknown Error'; |
23 |
break; |
24 |
}; |
25 |
|
26 |
console.log(msg); |
27 |
}; |
Objek filesystem Anda memperoleh memiliki nama (nama unik untuk filesystem, ditugaskan oleh browser) dan properti yang merujuk ke direktori root dari filesystem root. Ini adalah objek, dan mungkin memiliki direktori bersarang yang sendirinya diwakili oleh benda-benda konstruktor. Setiap direktori dalam sistem file dapat berisi file, diwakili oleh FileEntry objek. Objek mendefinisikan metode untuk memperoleh konstruktor dan FileEntry objek dengan path (mereka akan opsional membuat file direktori baru atau jika Anda menetapkan nama yang tidak ada). Konstruktor juga mendefinisikan createReader() pabrik metode yang mengembalikan sebuah objek DirectoryReader untuk daftar isi dari direktori. Kelas FileEntry mendefinisikan sebuah metode untuk mendapatkan File objek (gumpalan) yang mewakili isi dari file. Anda dapat menggunakan sebuah objek FileReader untuk membaca file. FileEntry mendefinisikan metode lain untuk mengembalikan sebuah objek FileWriter yang dapat Anda gunakan untuk menulis konten ke dalam file.
Phhew... terdengar rumit? Jangan khawatir. Semuanya akan menjadi semakin jelas apabila kita maju melalui contoh di bawah.
Langkah 2 - bekerja dengan direktori
Jelas, hal pertama yang Anda butuhkan untuk membuat di sebuah filesistem adalah beberapa ember, atau direktori. Meskipun direktori root sudah ada, Anda tidak ingin menempatkan semua file Anda tidak. Direktori dibuat oleh objek DirectoryEntry. Dalam contoh berikut, kita membuat direktori, yang disebut Dokumen, dalam direktori root:
1 |
fs.root.getDirectory('Documents', {create: true}, function(dirEntry) { |
2 |
alert('You have just created the ' + dirEntry.name + ' directory.'); |
3 |
}, errorHandler); |
GetDirectory() metode yang digunakan baik untuk membaca dan membuat direktori. Sebagai parameter, Anda dapat melewati jalan atau nama sebagai direktori untuk mencari atau membuat. Kami menetapkan argumen kedua ke true, karena kita sedang berusaha untuk menciptakan sebuah direktori - tidak membaca yang sudah ada. Dan pada akhirnya, kita menambahkan kesalahan callback.
Sejauh ini baik-baik saja. Kami memiliki direktori; Mari kita sekarang menambahkan sebuah subdirektori. Fungsi adalah persis sama dengan satu perbedaan: kita mengubah argumen pertama dari 'Dokumen' ke 'Dokumen/musik'. Mudah cukup; tetapi bagaimana jika Anda ingin membuat subfolder, langit, dengan dua folder induk, gambar dan alam, di dalam folder dokumen? Jika Anda mengetik ' Dokumen/foto/alam/Sky' untuk argumen path, Anda akan menerima kesalahan, karena Anda tidak dapat membuat direktori, ketika induknya langsung tidak ada. Solusi untuk ini adalah untuk membuat setiap folder satu per satu: gambar di dalam dokumen, alam di dalam gambar, dan kemudian langit di dalam alam. Tapi ini adalah proses yang sangat lambat dan tidak nyaman. Ada solusi yang lebih baik: untuk membuat fungsi yang akan membuat semua perlu folder secara otomatis.
1 |
function createDir(rootDir, folders) { |
2 |
rootDir.getDirectory(folders[0], {create: true}, function(dirEntry) { |
3 |
if (folders.length) { |
4 |
createDir(dirEntry, folders.slice(1)); |
5 |
} |
6 |
}, errorHandler); |
7 |
}; |
8 |
|
9 |
createDir(fs.root, 'Documents/Images/Nature/Sky/'.split('/')); |
Dengan trik kecil ini, yang perlu kita lakukan adalah memberikan path lengkap mewakili folder yang kita ingin membuat. Sekarang, direktori Sky berhasil dibuat, dan Anda dapat membuat file lain atau direktori di dalamnya.
Sekarang saatnya untuk memeriksa apa yang kita miliki di filesystem kami. Kami akan membuat objek DirectoryReader, dan menggunakan metode readEntries() untuk membaca isi dari direktori.
1 |
fs.root.getDirectory('Documents', {}, function(dirEntry){<br> |
2 |
var dirReader = dirEntry.createReader(); |
3 |
dirReader.readEntries(function(entries) {<br> |
4 |
for(var i = 0; i < entries.length; i++) { |
5 |
var entry = entries[i]; |
6 |
if (entry.isDirectory){ |
7 |
console.log('Directory: ' + entry.fullPath); |
8 |
} |
9 |
else if (entry.isFile){ |
10 |
console.log('File: ' + entry.fullPath); |
11 |
} |
12 |
} |
13 |
|
14 |
}, errorHandler); |
15 |
}, errorHandler); |
Pada kode di atas, sifat isDirectory dan isFile yang digunakan untuk mendapatkan output yang berbeda untuk direktori dan file, masing-masing. Selain itu, kita menggunakan fullPath properti untuk mendapatkan path lengkap dari entri, bukan hanya namanya.
Ada dua cara untuk menghapus konstruktor dari filesystem: remove() dan removeRecursively(). Pertama menghapus direktori diberikan hanya jika kosong. Jika tidak, Anda akan menerima galat.
1 |
fs.root.getDirectory('Documents/Music', {}, function(dirEntry) { |
2 |
dirEntry.remove(function(){ |
3 |
console.log('Directory successfully removed.'); |
4 |
}, errorHandler); |
5 |
}, errorHandler); |
Jika folder musik memiliki file di dalamnya, maka Anda perlu menggunakan metode kedua, yang secara rekursif menghapus direktori dan isinya.
1 |
fs.root.getDirectory('Documents/Music', {}, function(dirEntry) { |
2 |
dirEntry.removeRecursively(function(){ |
3 |
console.log('Directory successufully removed.'); |
4 |
}, errorHandler); |
5 |
}, errorHandler); |
Langkah 3 - bekerja dengan file
Sekarang bahwa kita tahu cara membuat direktori, saatnya untuk mengisi mereka dengan file!
Contoh berikut membuat test.txt
kosong di direktori root:
1 |
fs.root.getFile('test.txt', {create: true, exclusive: true}, function(fileEntry) { |
2 |
alert('A file ' + fileEntry.name + ' was created successfully.'); |
3 |
}, errorHandler); |
Argumen pertama untuk getFile()
bisa menjadi jalur absolut atau relatif, tetapi harus valid. Misalnya, ini adalah kesalahan untuk mencoba membuat file, ketika induk langsungnya tidak ada. Argumen kedua adalah objek literal, menggambarkan perilaku fungsi jika file tidak ada. Dalam contoh ini, create: true
membuat file jika tidak ada dan melempar kesalahan jika itu (exclusive: true
). Jika tidak, jika create: false
, file tersebut hanya diambil dan dikembalikan.
Memiliki file kosong tidak terlalu berguna; jadi mari tambahkan beberapa konten di dalamnya. Kita bisa menggunakan objek FileWriter untuk ini.
1 |
fs.root.getFile('test.txt', {create: false}, function(fileEntry) { |
2 |
fileEntry.createWriter(function(fileWriter) { |
3 |
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; |
4 |
var bb = new BlobBuilder(); |
5 |
bb.append('Filesystem API is awesome!'); |
6 |
fileWriter.write(bb.getBlob('text/plain')); |
7 |
}, errorHandler); |
8 |
}, errorHandler); |
Di atas, kita mengambil file test.txt, dan membuat objek FileWriter untuk itu. Kami kemudian menambahkan konten ke dalamnya dengan membuat objek BlobBuilder baru dan menggunakan metode write () FileWriter.
Memanggil getFile()
hanya mengambil FileEntry
. Itu tidak mengembalikan isi file. Jadi, jika kita ingin membaca isi file, kita perlu menggunakan objek File
dan objek FileReader
.
1 |
fs.root.getFile('test.txt', {}, function(fileEntry) { |
2 |
fileEntry.file(function(file) { |
3 |
var reader = new FileReader(); |
4 |
reader.onloadend = function(e) { |
5 |
alert(this.result); |
6 |
}; |
7 |
reader.readAsText(file); |
8 |
}, errorHandler); |
9 |
}, errorHandler); |
Kami telah menulis beberapa konten ke file kami, tetapi bagaimana jika keinginan untuk menambahkan lebih banyak di kemudian hari? Untuk menambahkan data ke file yang ada, FileWriter
digunakan sekali lagi. Kita dapat memposisikan ulang penulis di akhir file, menggunakan metode seek()
. seek
menerima offset byte sebagai argumen, dan menetapkan posisi penulis file ke offset tersebut.
1 |
fs.root.getFile('test.txt', {create: false}, function(fileEntry) { |
2 |
fileEntry.createWriter(function(fileWriter) { |
3 |
fileWriter.seek(fileWriter.length); |
4 |
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; |
5 |
var bb = new BlobBuilder(); |
6 |
bb.append('Yes, it is!'); |
7 |
fileWriter.write(bb.getBlob('text/plain')); |
8 |
}, errorHandler); |
9 |
}, errorHandler); |
Untuk menghapus file dari sistem file, cukup panggil entry.remove()
. Argumen pertama untuk metode ini adalah fungsi callback nol-parameter, yang dipanggil ketika file berhasil dihapus. Yang kedua adalah callback kesalahan opsional jika ada kesalahan.
1 |
fs.root.getFile('test.txt', {create: false}, function(fileEntry) { |
2 |
fileEntry.remove(function() { |
3 |
console.log('File successufully removed.'); |
4 |
}, errorHandler); |
5 |
}, errorHandler); |
Langkah 4 - Memanipulasi File dan Direktori
FileEntry dan DirectoryEntry berbagi metode API yang sama untuk menyalin, memindahkan, dan mengganti nama entri. Ada dua metode yang dapat Anda gunakan untuk operasi ini: copyTo () dan moveTo (). Mereka berdua menerima parameter yang sama persis:
1 |
copyTo(parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback); |
2 |
|
3 |
moveTo(parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback); |
Parameter pertama adalah folder induk untuk memindahkan / menyalin entri ke dalam. Yang kedua adalah nama baru opsional untuk memberikan entri yang dipindahkan / disalin, yang sebenarnya diperlukan saat Anda menyalin entri di folder yang sama; jika tidak, Anda akan mendapatkan kesalahan. Parameter ketiga dan keempat dijelaskan sebelumnya.
Mari kita tinjau beberapa contoh sederhana. Dalam yang berikut, kita salin file test.txt dari root ke direktori Dokumen.
1 |
function copy(currDir, srcEntry, destDir) { |
2 |
currDir.getFile(srcEntry, {}, function(fileEntry) { |
3 |
currDir.getDirectory(destDir, {}, function(dirEntry) { |
4 |
fileEntry.copyTo(dirEntry); |
5 |
}, errorHandler); |
6 |
}, errorHandler); |
7 |
} |
8 |
|
9 |
copy(fs.root, 'test.txt', 'Documents/'); |
Contoh berikut ini menggerakkan test.txt ke Dokumen, alih-alih menyalinnya:
1 |
function move(currDir, srcEntry, dirName) { |
2 |
currDir.getFile(srcEntry, {}, function(fileEntry) { |
3 |
currDir.getDirectory(dirName, {}, function(dirEntry) { |
4 |
fileEntry.moveTo(dirEntry); |
5 |
}, errorHandler); |
6 |
}, errorHandler); |
7 |
} |
8 |
|
9 |
move(fs.root, 'test.txt', 'Documents/'); |
Contoh berikut mengganti nama test.txt
menjadi text.txt
:
1 |
function rename(currDir, srcEntry, newName) { |
2 |
currDir.getFile(srcEntry, {}, function(fileEntry) { |
3 |
fileEntry.moveTo(currDir, newName); |
4 |
}, errorHandler); |
5 |
} |
6 |
|
7 |
rename(fs.root, 'test.txt', 'text.txt'); |
Belajarlah lagi
Dalam tutorial pengantar ini, kami hanya menggaruk permukaan antarmuka sistem berkas yang berbeda. Jika Anda ingin mempelajari lebih lanjut dan menggali lebih dalam ke API Filesystem, Anda harus merujuk ke spesifikasi spesifikasi W3C:
Sekarang setelah Anda memiliki pemahaman dasar tentang apa API Filesystem itu, dan bagaimana ia bisa digunakan, itu harus jauh lebih mudah untuk memahami dokumentasi API, yang dapat sedikit membingungkan pada pandangan pertama.
Kesimpulan
The Filesystem API adalah teknologi yang kuat dan mudah digunakan, yang memberikan pengembang web dengan segudang kemungkinan baru ketika membangun aplikasi web. Diakui, itu masih cukup baru dan tidak didukung secara luas oleh semua browser utama, tetapi ini pasti akan berubah di masa depan. Anda mungkin juga mendapatkan permulaan!