LoginSignup
0
1

More than 3 years have passed since last update.

AndroidでFirebaseStorageに複数のファイルをZipにしてアップロードする。

Posted at

1.複数のファイルをアップロードできない!

AndroidFirebaseStorageを使っているとき当然複数のファイルを一回にアップロードすることは当然あります。しかし、現在そのようなAPIは提供されていません。困った困った...。ということで複数のファイルをZipにまとめてアップロードすることにしました。

2.実装

SimpleFirebaseStorageDatabase.java
import android.content.Context;
import android.net.Uri;
import android.util.Log;

import androidx.annotation.NonNull;


import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class SimpleFirebaseStorageDatabase {

    private static final String TAG = "SimpleFirebaseStorageDB";
    private String userId;
    private StorageReference storageRef;
    private DatabaseReference databaseRef;
    private Context mContext;

    private static final long MAX_DOWNLOAD_SIZE = 1024 * 1024 * 5;

    public SimpleFirebaseStorageDatabase (Context context, FirebaseAuth mAuth, String firebaseStorageBucketToken) {
        mContext = context;
        FirebaseUser user = mAuth.getCurrentUser();
        if (user == null) {
            return;
        }
        this.userId =  user.getUid();
        storageRef = FirebaseStorage.getInstance().getReferenceFromUrl(firebaseStorageBucketToken).child("users").child(userId);
    }
    public void uploadFilesByTempFile (final String projectName, List<String> uris) {

        File zip = zipFilesToFile(projectName, uris);
        if (zip == null) {
            Log.e(TAG, "No zip file is created: " + projectName);
            return;
        }
        try {
            storageRef.child(projectName).putFile(Uri.fromFile(zip)).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess (UploadTask.TaskSnapshot taskSnapshot) {
                    Log.d(TAG, "Succeeded to upload project : " + projectName);
                    storageRef.child(projectName).getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                        @Override
                        public void onSuccess (Uri uri) {
                            Log.d(TAG, "Succeeded to get download url : " + uri);
                            onUploadSuccess(uri.toString());
                        }
                    }).addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure (@NonNull Exception e) {
                            Log.e(TAG, "Failed to get download url : " + projectName, e);
                            onUploadFail();
                        }
                    });
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure (@NonNull Exception e) {
                    Log.e(TAG, "Failed to upload project : " + projectName, e);
                    onUploadFail();
                }
            });
        } catch (Exception e) {
            onUploadFail();
        }

    }

    private File zipFilesToFile(String projectName, List<String> uris) {
        try {
            File projFile = new File(mContext.getFilesDir(), projectName);
            Log.d(TAG, "Make project zip file: " + projFile.getPath());
            // String outfilePath で出力先のファイルパスが指定されているとする
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(projFile));
            byte[] buffer = new byte[1024 * 4];
            int len = 0;

            // 引数などで String[] files として zip に追加したいファイルのファイルパスが指定されているとする
            for (String uri : uris) {
                zipOneFile(uri, out, buffer);
            }
            out.close();
            Log.d(TAG, "Succeeded to make project zip file: " + projFile.getPath());
            return projFile;
        } catch(Exception e){
            // エラー処理
            Log.e(TAG, "Failed to make project zip file: " + projectName, e);
        }
        return null;
    }


    /**
     * 指定Uriの1ファイルをZIPに追加する。
     * @param uri 圧縮するファイルのパス(Uri)
     * @param os
     * @param buffer
     */
    private static void zipOneFile(String uri, ZipOutputStream os, byte[] buffer) {
        InputStream in = null;
        int len = 0;
        try {
            Log.d(TAG, "Zip one file : " + uri);
            String path = Uri.parse(uri).getPath();
            File inFile = new File(path);
            if (!inFile.exists()) {
                Log.w(TAG, "File doesn't exist: " + uri);
                return;
            }

            in = new FileInputStream(inFile);
            os.putNextEntry(new ZipEntry(inFile.getName())); // path名からファイル名だけにしておく
            while ((len = in.read(buffer)) > 0) {
                os.write(buffer, 0, len);
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to zip file: " + uri, e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {
                    // do nothing
                }
            }
        }
    }

    private void onUploadSuccess (String downloadUri) {
        if (mContext instanceof OnFirebaseStorageUploadListener) {
            ((OnFirebaseStorageUploadListener) mContext).onUploadSucceed(downloadUri);
        }
    }

    private void onUploadFail () {
        if (mContext instanceof OnFirebaseStorageUploadListener) {
            ((OnFirebaseStorageUploadListener) mContext).onUploadFailed();
        }
    }

    public interface OnFirebaseStorageUploadListener {
        void onUploadSucceed (String downloadUri);
        void onUploadFailed ();
    }

3.使用方法

MainActivity.java
public class MainActivity extends AppCompatActivity implements SimpleFirebaseStorageDatabase.OnFirebaseStorageUploadListener{

    private List<String> mUriList;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SimpleFirebaseStorageDatabase firebaseStorage = new SimpleFirebaseStorageDatabase(ShareProjectActivity.this, mAuth, "バッケトトークン");
        mUriList = // ...
        firebaseStorage.uploadFilesByTempFile("ファイル名.zip", mUriList);
    }

    @Override
    public void onUploadSucceed (String downloadUri) {
        // 成功
    }

    @Override
    public void onUploadFailed () {
        // 失敗
    }

まとめ

今回は解説なしです。これに対応するダウンロードの処理は後日また書きます。
Firebaseを利用する際に必要になるログイン処理に関してはこちら
Twitter(フォローよろしくお願いします。): https://twitter.com/Cyber_Hacnosuke

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1