Thư mục tài liệu ứng dụng là bộ lưu trữ vĩnh viễn các tệp người dùng cần được giữ lại giữa các phiên và khôi phục từ bản sao lưu. Theo Apple File System Programming Guide, 2026, trên iOS, thư mục Documents được tự động bao gồm trong bản sao lưu iCloud, không giống như bộ nhớ đệm và các thư mục tạm thời. Sử dụng đúng cách thư mục tài liệu đảm bảo rằng các tệp người dùng không bị mất khi cập nhật hoặc cài đặt lại ứng dụng.
Những Điểm Chính
context.filesDir với quản lý sao lưu thủ côngThư mục tài liệu là một bộ lưu trữ chuyên dụng bên trong hộp cát (sandbox) của ứng dụng, được thiết kế để lưu trữ vĩnh viễn các tệp người dùng. Không giống như bộ nhớ đệm, các tệp trong thư mục này được coi là quan trọng đối với người dùng: hệ thống không xóa chúng khi thiếu dung lượng, chúng được giữ lại khi cập nhật ứng dụng và được sao lưu khi đồng bộ thiết bị. Trên iOS, thư mục Documents là một phần của vùng chứa Sandbox và tự động được bao gồm trong bản sao lưu iCloud. Trên Android, không có tương đương trực tiếp — tương đương là context.filesDir, cũng dành cho các tệp vĩnh viễn nhưng không có cơ chế sao lưu tích hợp.
Sự khác biệt giữa thư mục tài liệu và bộ nhớ trong trên Android là rất nhỏ: cả hai đều nằm trong hộp cát của ứng dụng, cả hai đều bị xóa khi gỡ cài đặt, cả hai đều không thể truy cập được bởi các ứng dụng khác. Sự khác biệt chính là về mặt ngữ nghĩa: Thư mục Tài liệu giả định rằng các tệp được tạo hoặc nhập bởi người dùng, trong khi Bộ nhớ trong có thể chứa các tệp nội bộ của ứng dụng (cơ sở dữ liệu, cấu hình). Trên iOS, sự khác biệt lớn hơn: Documents được sao lưu tự động, trong khi Library/Application Support thì không. Điều này ảnh hưởng đến chiến lược lưu trữ: chỉ đặt những gì người dùng muốn khôi phục trên thiết bị mới vào Documents và dữ liệu nội bộ mà ứng dụng có thể tái tạo vào Application Support.
Kiến trúc hộp cát đảm bảo rằng các ứng dụng khác không thể truy cập vào thư mục tài liệu của ứng dụng bạn. Trên iOS, không thể truy cập Documents của ứng dụng khác nếu không jailbreak. Trên Android, quyền truy cập root cho phép đọc filesDir của bất kỳ ứng dụng nào, vì vậy dữ liệu nhạy cảm (mã thông báo, khóa mã hóa) phải được bảo vệ thêm bằng EncryptedSharedPreferences hoặc EncryptedFile từ thư viện AndroidX Security.
Thư mục tài liệu nên lưu trữ dữ liệu có giá trị đối với người dùng và phải có thể truy cập sau khi khởi động lại ứng dụng hoặc khôi phục thiết bị. Không phải tất cả các tệp đều phù hợp để lưu trữ trong thư mục này — việc lựa chọn phụ thuộc vào loại dữ liệu và kịch bản sử dụng.
Các tệp người dùng là nội dung chính của thư mục tài liệu. Đây có thể là tài liệu văn bản được tạo trong trình soạn thảo, hình ảnh chụp bằng camera ứng dụng, báo cáo PDF đã xuất, bản ghi âm, ghi chú. Mỗi tệp như vậy được tạo bởi người dùng hoặc theo yêu cầu của họ và phải có thể truy cập bất cứ lúc nào. Trên iOS, các tệp từ Documents được hiển thị trong ứng dụng Tệp của hệ thống, cho phép người dùng quản lý chúng thông qua trình quản lý tệp tiêu chuẩn. Trên Android, không có hiển thị tương tự — ứng dụng phải tự cung cấp giao diện để xem các tệp đã lưu.
Cơ sở dữ liệu SQLite và các tệp cài đặt thường được lưu trữ gần thư mục tài liệu nhưng không nằm trong đó. Trên iOS, cơ sở dữ liệu được đặt trong Library/Application Support, vì chúng không nên xuất hiện trong ứng dụng Tệp và được sao lưu riêng. Trên Android, cơ sở dữ liệu được tạo mặc định trong /data/data/<package>/databases/ thông qua Room hoặc SQLiteOpenHelper. Nếu cơ sở dữ liệu chứa nội dung người dùng (ghi chú, nhật ký, hồ sơ tài chính), nó có thể được đặt trong filesDir để đảm bảo sao lưu hệ thống. Room cho phép chỉ định một thư mục lưu trữ tùy chỉnh cho cơ sở dữ liệu thông qua callback RoomDatabase.Builder.
val dbFile = File(context.filesDir, "user_database.db")
val db = Room.databaseBuilder<AppDatabase>(
context,
dbFile.absolutePath
).build()
Các tệp mà người dùng nhập từ các ứng dụng khác hoặc xuất từ ứng dụng của bạn cũng nên được lưu trong thư mục tài liệu. Trên iOS, việc nhập qua UIDocumentPickerViewController tự động đặt một bản sao của tệp vào Documents khi sử dụng tham số asCopy: true. Trên Android, việc nhập qua hộp thoại SAF cũng tạo một bản sao của tệp trong hộp cát của ứng dụng. Khi xuất dữ liệu (ví dụ: tạo tệp CSV với danh bạ), hãy lưu tệp trước trong Documents/filesDir, sau đó đề nghị người dùng chia sẻ tệp qua Share Sheet. Điều này đảm bảo rằng ngay cả khi người dùng quên lưu tệp sau khi gửi, một bản sao vẫn còn trong ứng dụng để sử dụng sau.
Trên Android, chức năng của thư mục tài liệu được thực hiện bởi context.filesDir. Ngoài ra, thư mục context.externalFilesDir trên thẻ SD có sẵn nhưng không đảm bảo tính toàn vẹn dữ liệu. Hãy xem xét các kỹ thuật chính để làm việc với các thư mục này.
filesDir là thư mục chính cho các tệp vĩnh viễn của ứng dụng trên Android. Nó nằm trong hộp cát của ứng dụng và bị xóa hoàn toàn khi gỡ cài đặt. Để có được một phiên bản File, hãy sử dụng context.filesDir, trả về đường dẫn đến /data/data/<package>/files/. Để tạo và đọc tệp, hãy sử dụng các thao tác Java/Kotlin File tiêu chuẩn hoặc các phương thức Context openFileInput() và openFileOutput(), nhận tên tệp và trả về FileInputStream/FileOutputStream. Phương thức openFileOutput() tự động tạo tệp trong filesDir nếu tệp chưa tồn tại và cho phép chỉ định chế độ truy cập: MODE_PRIVATE (chỉ ứng dụng hiện tại), MODE_APPEND (thêm vào) hoặc MODE_WORLD_READABLE (không được dùng nữa, không sử dụng từ API 24+).
val fileName = "report.pdf"
val content = "PDF content".toByteArray()
context.openFileOutput(fileName, Context.MODE_PRIVATE).use { stream ->
stream.write(content)
}
val bytes = context.openFileInput(fileName).use { stream ->
stream.readBytes()
}
Trên Android 10+, mô hình Scoped Storage không ảnh hưởng đến filesDir — quyền truy cập đầy đủ vào hộp cát riêng của ứng dụng vẫn được giữ nguyên. Tất cả các thao tác đọc và ghi trong filesDir không yêu cầu thêm quyền. Tuy nhiên, nếu bạn cố gắng truy cập tệp của ứng dụng khác qua filesDir, bạn sẽ nhận được một ngoại lệ. Để chia sẻ tệp, hãy sử dụng FileProvider, tạo một URI nội dung tạm thời để chuyển tệp sang ứng dụng khác. FileProvider được khai báo trong AndroidManifest.xml thông qua thẻ <provider> và được cấu hình trong tệp XML đường dẫn. Đây là cơ chế tiêu chuẩn để chuyển tệp giữa các ứng dụng, được sử dụng ví dụ khi gửi hình ảnh qua Intent với ACTION_SEND.
Trên iOS, Documents Directory là một phần của vùng chứa Sandbox của ứng dụng với trạng thái đặc biệt. Các tệp từ thư mục này được tự động bao gồm trong bản sao lưu iCloud, hiển thị trong ứng dụng Tệp và được giữ lại khi cập nhật ứng dụng qua App Store.
Sao lưu tự động Documents là một lợi thế chính của iOS. Khi người dùng kết nối thiết bị với iTunes hoặc bật iCloud Backup, tất cả các tệp từ Documents/ được sao chép vào bản sao lưu. Khi khôi phục trên thiết bị mới, người dùng nhận được tất cả các tệp của họ mà không cần thao tác thêm. Tuy nhiên, lợi thế này trở thành bất lợi nếu ứng dụng lưu trữ lượng lớn dữ liệu trong Documents: thời gian sao lưu tăng lên và dung lượng iCloud có thể nhanh chóng cạn kiệt. Do đó, Documents chỉ nên lưu trữ các tệp mà người dùng thực sự cần khi khôi phục. Các tệp tạm thời, bộ nhớ đệm và dữ liệu có thể tái tạo nên nằm trong Caches hoặc Library/Application Support. Apple khuyến nghị loại trừ khỏi sao lưu các tệp có thể tải xuống lại từ internet, thông qua thuộc tính isExcludedFromBackup.
let fm = FileManager.default
let docsURL = fm.urls(
for: .documentDirectory,
in: .userDomainMask
).first!
let fileURL = docsURL.appendingPathComponent("notes.txt")
let text = "Nội dung ghi chú"
try text.write(to: fileURL, atomically: true, encoding: .utf8)
iCloud Drive cho phép đồng bộ các tệp từ Documents giữa các thiết bị của người dùng. Để kích hoạt đồng bộ, ứng dụng nên sử dụng API NSDocument hoặc UIDocument, tự động quản lý việc kiểm soát phiên bản và giải quyết xung đột. Một cách tiếp cận khác là sử dụng iCloud với CloudKit, cung cấp khả năng kiểm soát đồng bộ linh hoạt hơn nhưng yêu cầu cấu hình trên CloudKit Dashboard. Khi sử dụng iCloud Drive, hãy đảm bảo bạn xử lý chính xác các xung đột chỉnh sửa (hợp nhất hoặc người ghi cuối thắng) và thông báo cho người dùng về trạng thái đồng bộ qua giao diện ứng dụng. iCloud không đảm bảo đồng bộ tức thì — độ trễ có thể từ vài giây đến vài phút tùy thuộc vào kích thước tệp và chất lượng kết nối. Đối với dữ liệu quan trọng, hãy sử dụng ghi giao dịch và kiểm soát phiên bản để trong trường hợp xung đột, có thể khôi phục phiên bản trước của tệp.
Lựa chọn đúng giữa Documents Directory và Cache Directory quyết định độ tin cậy của việc lưu trữ dữ liệu người dùng. Sai lầm trong lựa chọn dẫn đến mất dữ liệu (nếu tệp quan trọng được lưu trong bộ nhớ đệm) hoặc tràn bản sao lưu (nếu tệp tạm thời được lưu trong Documents).
| Tiêu chí | Documents Directory | Cache Directory |
|---|---|---|
| Đảm bảo tính toàn vẹn | Cao — không bị hệ thống xóa | Thấp — có thể bị dọn |
| Sao lưu (iOS) | Tự động trong iCloud | Không được sao lưu |
| Hiển thị với người dùng (iOS) | Trong ứng dụng Tệp | Ẩn |
| Dọn dẹp khi cập nhật | Không bị dọn | Có thể bị dọn |
| Kích thước khuyến nghị | Bất kỳ, nhưng kiểm soát qua cài đặt | Đến 100–200 MB |
| Loại dữ liệu | Tệp người dùng | Dữ liệu tạm thời có thể tái tạo |
Thực hành tốt nhất khi sử dụng thư mục tài liệu bao gồm một số quy tắc chính. Thứ nhất, luôn yêu cầu xác nhận của người dùng trước khi xóa tệp khỏi thư mục này. Không giống như bộ nhớ đệm, xóa một tài liệu có thể dẫn đến mất nội dung người dùng không thể khôi phục. Thứ hai, triển khai kiểm soát phiên bản tệp: khi ghi đè lên tệp hiện có, hãy lưu phiên bản trước với hậu tố _backup hoặc sử dụng cơ chế Snapshot. Thứ ba, cung cấp cho người dùng giao diện để xem, đổi tên, xóa và xuất tệp từ thư mục tài liệu. Trên iOS, các tệp từ Documents tự động hiển thị trong Tệp; trên Android, bạn cần triển khai trình quản lý tệp của riêng mình hoặc sử dụng thư viện bên thứ ba.
Đặc biệt chú ý đến di chuyển dữ liệu khi cập nhật ứng dụng. Nếu phiên bản mới thay đổi cấu trúc lưu trữ tệp (ví dụ: di chuyển dữ liệu từ thư mục con này sang thư mục con khác hoặc thay đổi định dạng tệp), hãy triển khai di chuyển một lần khi khởi chạy lần đầu sau khi cập nhật. Lưu số phiên bản lược đồ dữ liệu trong SharedPreferences và chạy di chuyển nếu chúng không khớp. Không xóa tệp cũ trước khi hoàn tất di chuyển — trong trường hợp lỗi, người dùng không nên mất dữ liệu. Nếu di chuyển bao gồm chuyển đổi định dạng (ví dụ: chuyển từ JSON sang SQLite), hãy lưu các tệp gốc làm bản sao lưu trong một thư mục riêng với ngày di chuyển. Người dùng sẽ có thể hoàn tác các thay đổi thông qua cài đặt ứng dụng trong vòng 30 ngày đầu sau khi cập nhật, theo khuyến nghị của Apple Human Interface Guidelines.
Câu hỏi Thường gặp
Documents được hiển thị trong ứng dụng Tệp và tự động sao lưu vào iCloud. Application Support không hiển thị trong Tệp và không được sao lưu mặc định. Chọn Application Support cho dữ liệu nội bộ của ứng dụng mà bạn không cần hiển thị cho người dùng.
Có, khi xóa tài khoản, hãy đề nghị người dùng dọn sạch tất cả tệp cục bộ liên quan đến tài khoản đó. Hiển thị hộp thoại hỏi “Xóa tất cả dữ liệu cục bộ?” và liệt kê những tệp nào sẽ bị ảnh hưởng. Đây là yêu cầu GDPR và tuân thủ chính sách của App Store và Google Play.
Trên iOS, chỉ cần khôi phục thiết bị từ bản sao lưu iCloud hoặc iTunes — các tệp từ Documents được khôi phục tự động. Trên Android, sử dụng API Google Drive Backup để sao lưu tệp từ filesDir hoặc triển khai xuất qua dịch vụ đám mây.
Trên iOS, người dùng có thể xóa tệp qua ứng dụng Tệp. Trên Android, việc xóa chỉ có thể thực hiện qua giao diện ứng dụng của bạn. Nên triển khai thùng rác tài liệu với khả năng khôi phục trong vòng 30 ngày sau khi xóa để ngăn mất dữ liệu vô tình.
Không cần thao tác thêm — iOS và Android tự động giữ lại thư mục tài liệu khi cập nhật qua App Store hoặc Google Play. Tuy nhiên, khi thay đổi cấu trúc lưu trữ, hãy triển khai di chuyển dữ liệu khi khởi chạy lần đầu phiên bản mới bằng cách kiểm tra số phiên bản lược đồ trong cài đặt.
Tóm tắt
context.filesDir làm tương đương — tệp được giữ lại khi cập nhật nhưng không có cơ chế sao lưu tích hợpChúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm