[JAVA] Zip and upload multiple files to Firebase Storage on Android.

1. I can't upload multiple files!

ʻWhen using Firebase Storage on Android`, it is natural to upload multiple files at once. However, no such API is currently available. I was in trouble ... So I decided to upload multiple files to Zip at once.

2. Implementation

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());
            //Suppose the output destination file path is specified in String outfilePath
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(projFile));
            byte[] buffer = new byte[1024 * 4];
            int len = 0;

            //String with arguments etc.[]Suppose the file path of the file you want to add to the zip is specified as files
            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){
            //Error handling
            Log.e(TAG, "Failed to make project zip file: " + projectName, e);
        }
        return null;
    }


    /**
     *Add one file of the specified Uri to ZIP.
     * @param uri path to the file to compress(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())); //Keep only the file name from the path name
            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. How to use

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, "Bucket token");
        mUriList = // ...
        firebaseStorage.uploadFilesByTempFile("file name.zip", mUriList);
    }

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

    @Override
    public void onUploadFailed () {
        //Failure
    }

Summary

There is no explanation this time. I will write about the corresponding download process later. For the login process required when using Firebase, click here [https://qiita.com/Cyber_Hacnosuke/items/0c291e240034872eba65) Twitter (Please follow me.): Https://twitter.com/Cyber_Hacnosuke

Recommended Posts

Zip and upload multiple files to Firebase Storage on Android.
Upload multiple images to Cloudinary on Active Storage and publish to Heroku
* Android * About saving / reading files to external storage and permissions
* Android * Saving / loading files to internal storage
Java upload and download notes to Azure storage
How to use OpenCV 4 on Android and view camera live view
How to place and share SwiftLint config files on the server
How to "hollow" View on Android
How to narrow down the image format from the gallery on Android and then select and import multiple images
[Android] How to turn the Notification panel on and off using StatusBarManager
Sample to display (head-up) notifications on Android
Run Embulk on Docker to convert files
How to detect microphone conflicts on Android
[Java] How to output and write files!
* Android * Saving / loading images to external storage
Java to C and C to Java in Android Studio
Steps to register Java files on GitHub
I tried using "nifty cloud mobile backend" and "Firebase" Authentication on Kotlin + Android