کار با فایل‌ها و پوشه‌ها - Android

در این مستند شما با همه‌ی قابلیت‌های سرویس فایل از طریق SDK اندروید آشنا خواهید شد.

پیش‌نیازها

  1. در صورتی که با سرویس فایل آشنایی ندارید، به معرفی سرویس فایل مراجعه کنید.
  2. در صورتی که هنوز در پنل توسعه‌دهنده خود تنظیمات لازم برای سرویس فایل خود را انجام نداده‌اید، به تنظیمات پنل مراجعه کنید.
  3. در صورتی که هنوز SDK اندروید را راه‌اندازی نکرده‌اید، به راه‌اندازی SDK بکتوری در اندروید مراجعه کنید.

راه‌اندازی سرویس فایل

در ابتدا برای آن که بتوانید اعمال مربوط به سرویس فایل را به کمک SDK بکتوری انجام دهید، می‌بایست در قسمت راه‌اندازی SDK تابع setFileStorageKey را اضافه کنید:

// Extending android application to initialize backtory
public class MainApplication extends Application {
    @Override
    public void onCreate(){
        super.onCreate();
        BacktoryClient.init(KeyConfiguration.newBuilder().
            setAuthKeys("<X-Backtory-Authentication-Id>",
                        "<X-Backtory-Authentication-Key (Client)>").
            setFileStorageKey("<X-Backtory-Storage-Id>").
            build(), this);
    }
}

آپلود فایل

نکته: دقت کنید که با توجه به ظرفیت کم حافظه در گوشی‌های موبایل، آپلود فایل به کمک sdk بکتوری فعلا تنها برای فایل‌های کم‌حجم در دسترس است و در غیر این صورت، خطر crash به خاطر کمبود memory وجود دارد. هم‌چنین، عمل آپلود محدود به زنده بودن اپلیکیشن است؛ یعنی، در صورتی که اپلیکیشن در میانه‌ی آپلود kill شود، عمل آپلود ناموفق خواهد بود.

برای آن‌که بتوانید یک فایل را از روی دستگاه موبایل کاربر به سرور بکتوری آپلود کنید، ابتدا باید یک «درخواست آپلود» (UploadRequest) را به کمک تابع beginUpload ایجاد کرده و سپس با صدا زدن تابع commitInBackground روی آن، درخواست اجرا شود، سرور را کال کرده و پاسخ را برگرداند. کد زیر این کارها را انجام می‌دهد:

new BacktoryFile().beginUpload(<YOUR-FILE-TO-UPLOAD>, uploadPath, true)
        .commitInBackground(new BacktoryCallBack<String>() {
            @Override
            public void onResponse(BacktoryResponse<String> response) {
                if (response.isSuccessful()) {
                    String filePathOnServer = response.body();
                    Log.d("TAG", "Upload was successful." +
                            " File path on server (url) is " + filePathOnServer);
                } else {
                    Log.d("TAG", "failed; " + response.message());
                }
            }
});

آرگومان‌هایی که تابع beginUpload دریافت می‌کند، به ترتیب به صورت زیر است:

نکته: در صورتی که پوشه‌های درخواست شده وجود نداشته باشد، سرویس آپلود به صورت پیشفرض این پوشه‌ها را خواهد ساخت.

در صورتی که عمل آپلود با موفقیت انجام شود، ()response.body برابر مسیر فایل آپلود شده خواهد بود. دقت کنید که این مسیر با رشته‌ی آرگومان uploadPath که شما به عنوان ورودی پاس داده‌اید، ممکن است در شرایطی فرق کند! در واقع، اگر رشته‌ی uploadPath صرفا شامل حروف کوچک یا بزرگ انگلیسی و یا اعداد باشد، عینا همان پوشه‌ی مشخص شده در ()response.body خواهد بود. اما در صورتی که شامل کارکترهای ویژه، کارکتر فاصله، حروف فارسی و … باشد، ()response.body رشته‌ی کاملا متفاوتی خواهد بود. به عنوان مثال، فرض کنید آدرس بارگذاری فایل به صورت

"/path/to/"

و نام فایل به صورت

"file 1 .txt"

باشد؛ یعنی، یک کارکتر فاصله قبل و بعد از حرف ۱ در نام فایل وجود داشته باشد. در این صورت، ()response.body به صورت

"/path/to/file%201%20.txt"

خواهد بود. بنابراین، مهم است که به جای رشته‌ی uploadPath، رشته‌ی ()response.body را به عنوان آدرس فایل روی سرور برای ارجاع‌های بعدی نگه دارید.

تغییر نام فایل

برای آن‌که بتوانید نام فایلی را که سمت سرور آپلود شده است، تغییر دهید، می‌بایست یک «درخواست تغییر نام» (RenameRequest) به کمک تابع beginRename ایجاد کرده و سپس به کمک commitInBackground آن را اجرا کنید. کد زیر این کار‌ها را انجام می‌دهد:

new BacktoryFile().beginRename("<FILE-URL>", "<NEW-NAME>")
        .commitInBackground(new BacktoryCallBack<String>() {
            @Override
            public void onResponse(BacktoryResponse<String> response) {
                if (response.isSuccessful()) {
                    String renamedFilePath = response.body();
                    Log.d("TAG", "Rename was successful." +
                            " New file url is " + renamedFilePath);
                } else {
                    Log.d("TAG", "failed; " + response.message());
                }
            }
});

آرگومان‌هایی که تابع beginRename دریافت می‌کند، به ترتیب به صورت زیر است:

در صورتی که عمل تغییر نام موفقیت‌آمیز باشد، ()response.body برابر آدرس جدید فایل در سمت سرور خواهد بود. دقت کنید که علاوه بر این‌که مشابه قسمت قبل، کارکترهای ویژه هم‌چون فاصله، & و … به صورت encode شده در پاسخ سرور ظاهر می‌شوند، رشته‌ی ()response.body حاوی یک ویژگی مهم دیگر نیز هست؛ و آن این‌که نام مخزن شما در ابتدای url برگردانده شده وجود دارد!

به عنوان مثال، فرض کنید آرگومان‌هایی که به تابع تغییر نام پاس می‌دهیم، به صورت زیر هستند:

String url = "/path/to/file1.txt";
String newName = "newFile 1&.txt";

در صورتی که عملیات تغییر نام موفقیت‌آمیز باشد، ()response.body برابر خواهد بود با

"/pegah/path/to/newFile%201%26.txt"

که pegah مثلا نام مخزن شماست! برای ارجاع‌های بعدی باید نام مخزن را از ابتدای پاسخ درخواست حذف کرده و رشته‌ی حاصل را نگاه دارید.

حذف فایل/پوشه

برای آن‌که یک فایل یا پوشه را در سمت سرور حذف کنید، می‌بایست یک «درخواست حذف» (DeleteRequest) به کمک تابع beginDelete ایجاد کرده و سپس، به کمک commitInBackground آن را اجرا کنید. کد زیر این کارها را انجام می‌دهد:

new BacktoryFile().beginDelete("<FILE-URL>", true)
        .commitInBackground(new BacktoryCallBack<Void>() {
            @Override
            public void onResponse(BacktoryResponse<Void> response) {
                if (response.isSuccessful()) {
                    Log.d("TAG", "Delete was successful.");
                } else {
                    Log.d("TAG", "failed; " + response.message());
                }
            }
        });

آرگومان‌هایی که تابع beginDelete دریافت می‌کند، به صورت زیر هستند:

اعمال دسته‌ای بر روی فایل‌ها

در قسمت‌های قبل یاد گرفتیم که چگونه می‌توان در sdk بکتوری تنها «یک» فایل را آپلود یا حذف کرد و یا تغییر نام داد. قابلیت دیگری که به کمک sdk وجود دارد، این است که همه‌ی این کارها را، نه روی «یک» فایل، بلکه روی «دسته‌ای» از فایل‌ها انجام دهیم. در ادامه با نحوه‌ی انجام این اعمال آشنا خواهید شد.

آپلود دسته‌ای فایل‌ها

برای آپلود فایل‌ها به صورت دسته‌ای کد زیر مورد استفاده قرار می‌گیرد:

File[] filesToUpload;
String[] uploadPaths;
boolean[] replacesIfSameNameExist;

// Initialize above variables here.

// Construct list of requests
List<Request.UploadRequest> uploadRequests = new ArrayList<>();
for(int i = 0; i < filesToUpload.length; i++) {
    uploadRequests.add(new BacktoryFile().beginUpload(
            filesToUpload[i],
            uploadPaths[i],
            replacesIfSameNameExist[i]));
}

// Run requests batch
new BulkOperation.BulkUpload(uploadRequests).commitInBackground(
        new BacktoryCallBack<List<String>>() {
            @Override
            public void onResponse(BacktoryResponse<List<String>> response) {
                if (response.isSuccessful()) {
                    List<String> filesPathsOnServer = response.body();
                    for (int i = 0; i < filesPathsOnServer.size(); i++)
                        Log.d("TAG", i + "'th file path on server: "
                                + filesPathsOnServer.get(i));
                } else {
                    Log.d("TAG", "failed; " + response.message());
                }
            }
});

در کد بالا، ابتدا شما لیستی از UploadRequestها را به کمک دستور beginUpload می‌سازید که توضیح آن در قسمت آپلود یک فایل رفت. سپس به کمک کلاس BulkOperation عملیات آپلود را به صورت دسته‌ای انجام می‌دهید. در پاسخ عملیات فوق، در صورتی که عملیات موفقیت‌آمیز باشد، ()response.body ‌شامل لیستی از مسیرهای نهایی آپلود شده‌ی فایل‌ها به ترتیب وقوع‌شان در لیست درخواست‌ها خواهد بود که در کد بالا، آن‌ها را به ترتیب لاگ زده‌ایم. دقت کنید که توضیحات قسمت‌های قبل در مورد تفاوت ()response.body با uploadPaths نیز کماکان در این‌جا برقرار هستند. یعنی، برای ارجاع‌های بعدی به فایل‌های آپلود شده نیاز است که از مسیرهای معتبر response.Body استفاده کنید.

تغییر نام دسته‌ای فایل‌ها

برای تغییر نام فایل‌ها به صورت دسته‌ای کد زیر مورد استفاده قرار می‌گیرد:

String[] filesUrls;
String[] newNames;

// Initialize above variables here.

// Construct list of requests
List<Request.RenameRequest> renameRequests = new ArrayList<>();
for(int i = 0; i < filesUrls.length; i++) {
    renameRequests.add(new BacktoryFile().beginRename(
            filesUrls[i],
            newNames[i]));
}

// Run requests batch
new BulkOperation.BulkRename(renameRequests).commitInBackground(
        new BacktoryCallBack<List<String>>() {
            @Override
            public void onResponse(BacktoryResponse<List<String>> response) {
                if (response.isSuccessful()) {
                    List<String> renamedFilesPaths = response.body();
                    for (int i = 0; i < renamedFilesPaths.size(); i++)
                        Log.d("TAG", i + "'th file path on server: "
                                + renamedFilesPaths.get(i));
                } else {
                    Log.d("TAG", "failed; " + response.message());
                }
            }
        });

در کد بالا، ابتدا شما لیستی از RenameRequestها را به کمک دستور beginRename می‌سازید که توضیح آن در قسمت تغییر نام یک فایل رفت. سپس به کمک کلاس BulkOperation عملیات تغییر نام را به صورت دسته‌ای انجام می‌دهید. در پاسخ عملیات فوق، در صورتی که عملیات موفقیت‌آمیز باشد، ()response.body ‌شامل لیستی از آدرس‌های جدید فایل‌ها به ترتیب وقوع‌شان در لیست درخواست‌ها خواهد بود که در کد بالا، آن‌ها را به ترتیب لاگ زده‌ایم. دقت کنید که توضیحات قسمت‌های قبل در مورد ویژگی‌های مهم ()response.body نیز کماکان در این‌جا برقرار هستند. یعنی، برای ارجاع‌های بعدی به فایل‌های تغییر نام یافته نیاز است که از مسیرهای معتبر ()response.body استفاده کرده و هم‌چنین، نام مخزن را از ابتدای تمامی آن‌ها حذف کنید.

حذف دسته‌ای فایل‌ها/پوشه‌ها

برای حذف فایل‌ها به صورت دسته‌ای کد زیر مورد استفاده قرار می‌گیرد:

String[] resourcesUrls;
boolean[] deleteDirectoryContentsList;

// Initialize above variables here.

// Construct list of requests
List<Request.DeleteRequest> deleteRequests = new ArrayList<>();
for(int i = 0; i < resourcesUrls.length; i++) {
    deleteRequests.add(new BacktoryFile().beginDelete(
            resourcesUrls[i],
            deleteDirectoryContentsList[i]));
}

// Run requests batch
new BulkOperation.BulkDelete(deleteRequests).commitInBackground(
        new BacktoryCallBack<Void>() {
            @Override
            public void onResponse(BacktoryResponse<Void> response) {
                if (response.isSuccessful()) {
                    Log.d("TAG", "Delete was successful.");
                } else {
                    Log.d("TAG", "failed; " + response.message());
                }
            }
        });

در کد بالا، ابتدا شما لیستی از DeleteRequestها را به کمک دستور beginDelete می‌سازید که توضیح آن در قسمت حذف یک فایل/پوشه رفت. سپس به کمک کلاس BulkOperation عملیات حذف را به صورت دسته‌ای انجام می‌دهید.

به این ترتیب، شما با همه‌ی قابلیت‌های sdk بکتوری برای کار با فایل‌ها و پوشه‌ها آشنا شدید.