2017-06-11 4 views
1

Ich versuche, mehrere Bilder auf Firebase-Speicher hochzuladen. Ich habe folgenden Code für diese geschrieben: -Hochladen mehrerer Bilder in Firebase-Speicher

private static void uploadImage(String imageUrl) 
    { 
     FirebaseStorage storage = FirebaseStorage.getInstance(); 
     final StorageReference storageRef = storage.getReferenceFromUrl("gs://image-store.appspot.com/"); 
     Uri file = Uri.fromFile(new File(imageUrl)); 
     String imageName = System.currentTimeMillis()+".jpg"; 
     StorageReference imageRef = storageRef.child("images").child(imageName); 
     UploadTask uploadTask = imageRef.putFile(file); 
    } 

    private static uploadImages(String[] imageUrls) 
    { 
     for(imageUrl : imageUrls) 
     { 
      uploadImage(imageUrl) 
     } 
    } 

Wenn es weniger Bilder, die obige Code funktioniert gut hochzuladen. Aber wenn es um eine mehr als 100 Bilder sind erstellt es mehrere asynchrone Threads und gibt den folgenden Fehler: -

Exception java.util.concurrent.RejectedExecutionException: Task [email protected] rejected from [email protected][Running, pool size = 2, active threads = 2, queued tasks = 128, completed tasks = 59] 
java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution (ThreadPoolExecutor.java:2042) 
java.util.concurrent.ThreadPoolExecutor.reject (ThreadPoolExecutor.java:796) 
java.util.concurrent.ThreadPoolExecutor.execute (ThreadPoolExecutor.java:1370) 
com.google.firebase.storage.zzd.zzu() 
com.google.firebase.storage.UploadTask.schedule() 
com.google.firebase.storage.StorageTask.an() 
com.google.firebase.storage.StorageReference.putFile() 
com.indiacom.blanketfos.util.FirebaseUtil.uploadImage (FirebaseUtil.java:64) 
com.indiacom.blanketfos.util.FirebaseUtil.uploadImages (FirebaseUtil.java:126) 
com.indiacom.blanketfos.util.FirebaseUtil.syncRealmToFirebase (FirebaseUtil.java:33) 
com.indiacom.blanketfos.ui.FormActivity.onOptionsItemSelected (FormActivity.java:406) 
android.app.Activity.onMenuItemSelected (Activity.java:2983) 
android.support.v4.app.FragmentActivity.onMenuItemSelected (FragmentActivity.java:408) 
android.support.v7.app.AppCompatActivity.onMenuItemSelected (AppCompatActivity.java:195) 
android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected (WindowCallbackWrapper.java:113) 
android.support.v7.app.AppCompatDelegateImplV9.onMenuItemSelected (AppCompatDelegateImplV9.java:675) 
android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected (MenuBuilder.java:822) 
android.support.v7.view.menu.MenuItemImpl.invoke (MenuItemImpl.java:156) 
android.support.v7.view.menu.MenuBuilder.performItemAction (MenuBuilder.java:969) 
android.support.v7.view.menu.MenuBuilder.performItemAction (MenuBuilder.java:959) 
android.support.v7.widget.ActionMenuView.invokeItem (ActionMenuView.java:623) 
android.support.v7.view.menu.ActionMenuItemView.onClick (ActionMenuItemView.java:154) 
android.view.View.performClick (View.java:4781) 
android.view.View$PerformClick.run (View.java:19907) 
android.os.Handler.handleCallback (Handler.java:739) 
android.os.Handler.dispatchMessage (Handler.java:95) 
android.os.Looper.loop (Looper.java:160) 
android.app.ActivityThread.main (ActivityThread.java:5541) 
java.lang.reflect.Method.invoke (Method.java) 
java.lang.reflect.Method.invoke (Method.java:372) 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:964) 
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:759) 

Also meine Frage ist, was das Beste ist und die effizienteste Art und Weise, ohne Landung mehrere Bilder Feuerbasis Speicher Hochladen in solche Probleme.

+2

Uploading 100 Bilder parallel klingt wie eine schlechte Idee. Ich würde eine angemessenere Anzahl paralleler Uploads (sagen wir 3-5) verwenden und nur einen neuen Upload starten, sobald einer der bestehenden Uploads abgeschlossen ist (Sie können [Fortschritt der Upload-Aufgabe überwachen] (https://firebase.google .com/docs/storage/android/upload-dateien # monitor_upload_progress)). –

+1

Wenn Sie Ihren Executor auf nur die Anzahl der Kerne auf dem Gerät beschränken, sagen wir 4, dann funktioniert es. Aber das macht natürlich alles viel langsamer. Die Veröffentlichung in der Firebase Echtzeit-Datenbank ist in Ordnung, aber ich denke, das ist sehr schnell, während das Hochladen langsam ist und einen Thread ergreift. Vielleicht sollten Sie erst eine neue Runnable-Task im Executor starten, nachdem alle UploadTasks abgeschlossen sind? –

+0

Verwenden Sie addOnCompleteListener, um eine leere Nachricht an Ihren Handler zu senden, damit der Download/Upload erneut gestartet wird. Das funktioniert für mich. –

Antwort

0

Ich hatte das gleiche Problem und Firebase-Speicher gefunden akzeptieren nur maximal 100 gleichzeitige Upload für kostenlose Konto. Also hier ist, was ich getan habe und hoffe, es hilft:

private static void uploadFS(final File[] files, final StorageReference certRef, int startIndex, int concurrent) { 
    int cnt = 0; 
    File file; 
    Uri uriFile; 
    StorageReference ref; 
    while (cnt < concurrent) { 
     file = files[startIndex]; 
     startIndex++; 
     if (file.exists() && file.length() > 0) { // local cert file exits 
      uriFile = Uri.fromFile(file); 
      final int sIdx = startIndex; 
      ref = certRef.child("cert/" + uriFile.getLastPathSegment()); 
      ref.putFile(uriFile).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { 
       @Override 
       public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { 
        uploadFS(files, certRef, sIdx, 1); 
       } 
      }); 
     } 
     cnt++; 
    } 
} 
public static void uploadCert() { 
    StorageReference rootStorageRef = getStorageRefRoot(); 
    if (rootStorageRef != null) { // loop through download folder 
     File certFolder = new File(MainActivity.DOWNLOAD_FULL_PATH + "cert/"); 
     if (certFolder.isDirectory()) { 
      File[] certFiles = certFolder.listFiles(); 
      uploadFS(certFiles, rootStorageRef, 0, 3); // 3 is concurrent upload tasks 
     } 
    } 
} 
Verwandte Themen