如何在将图像上传到 Firebase 存储之前对其进行压缩?

Posted

技术标签:

【中文标题】如何在将图像上传到 Firebase 存储之前对其进行压缩?【英文标题】:How to compress image before upload it to firebase storage? 【发布时间】:2022-01-18 18:57:58 【问题描述】:

我想在上传到 Firebase 存储之前减小图像文件的大小,因为上传需要很长时间。

这是一个包含edittext + imageview的表单

点击“保存”按钮时,我同时保存数据(实时数据库)和图像(存储)。

那么怎么做才能减小图片大小或者压缩呢??

public class PDV_form extends AppCompatActivity 

 @Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_pdv_form);
     imgproduit.setOnClickListener(new View.OnClickListener() 
         @Override
        public void onClick(View v) 
            selectImage();
         
    );

    Save.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
             rootNode = FirebaseDatabase.getInstance("https://dtechapp-94795-default-rtdb.europe-west1.firebasedatabase.app");
            reference = rootNode.getReference().child("pdv");

            String nomcmplt = nomCmplt.getEditText().getText().toString();
            String nompdv = nomPdv.getEditText().getText().toString();
            String phone = Phone.getEditText().getText().toString();
            String adresse = Adresse.getEditText().getText().toString();
            String commune = Commune.getEditText().getText().toString();
            String wilaya = Wilaya.getEditText().getText().toString();
            String codezip = Zip.getEditText().getText().toString();
            String email = Email.getEditText().getText().toString();
            String imagepdv = placeimgpdv.getDrawable().toString().trim();
                 UploadDialog = new ProgressDialog(PDV_form.this);
                UploadDialog.setTitle("Sauvegarde en cours.... ");
                UploadDialog.show();

                SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.FRANCE);
                Date now = new Date();
                String fileName = formatter.format(now);
                storageReference = FirebaseStorage.getInstance().getReference("pdv/" + fileName);
                storageReference.putFile(imageUri)
                        .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() 
                            @Override
                            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) 

                                placeimgpdv.setImageURI(null);
                                Toast.makeText(PDV_form.this, "Sauvegarde Terminée", Toast.LENGTH_SHORT).show();
                                if (UploadDialog.isShowing())
                                    UploadDialog.dismiss();

                            
                        ).addOnFailureListener(new OnFailureListener() 
                    @Override
                    public void onFailure(@NonNull Exception e) 
                         if (UploadDialog.isShowing())
                            UploadDialog.dismiss();
                        Toast.makeText(PDV_form.this, "Sauvegarde Annulée", Toast.LENGTH_SHORT).show();
                     
                );

                StorageReference filpath = storageReference;
                filpath.putFile(imageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() 
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) 
                        Task<Uri> downloadurl = taskSnapshot.getStorage().getDownloadUrl().addOnCompleteListener(new OnCompleteListener<Uri>() 
                            @Override
                            public void onComplete(@NonNull @NotNull Task<Uri> task) 
                                String t = task.getResult().toString();
                                DatabaseReference newPost = reference.child(nomcmplt + "(" + nompdv + ")");
                                newPost.child("nomcmplt").setValue(nomcmplt);
                                newPost.child("nompdv").setValue(nompdv);
                                newPost.child("phone").setValue(phone);
                                newPost.child("adresse").setValue(adresse);
                                newPost.child("commune").setValue(commune);
                                newPost.child("wilaya").setValue(wilaya);
                                newPost.child("codezip").setValue(codezip);
                                newPost.child("email").setValue(email);
                                newPost.child("imagepdv").setValue(task.getResult().toString());
                                newPost.child("user_id").setValue(uid);

                                if (task.isSuccessful()) 
                                    startActivity(new Intent(PDV_form.this, Bottom_bar.class));
                                
                            
                        );
                    
                );

         
    );



private void selectImage() 

    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    // intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    startActivityForResult(intent, Gallery_code);



public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == Gallery_code && resultCode == RESULT_OK) 
        imageUri = data.getData();
        placeimgpdv.setImageURI(imageUri);

    


【问题讨论】:

你的图片有多大? 4 到 6 MB 之间 可能重复***.com/questions/41611294/… 是的,我检查过了,但我不知道如何在我的代码中应用它!! 【参考方案1】:

您在问两个问题,一个是减小图像的大小,另一个是压缩它。我假设您打算通过减小大小而不是压缩它来以有损方式压缩图像。如果这不是您在 cmets 中的意思,请告诉我。

您可以选择手动构建解决方案。 Python 有很多很好的库可以帮助你做到这一点,对于 java,我确实找到了一些沿着这个方向工作的好资源,这个 SO 问题似乎很不错 - How can I compress images using java?

另一种选择是使用 SaaS 工具。这将真正为您简化过程,对于像这样简单的事情,除非您压缩大量图像或非常大的图像,否则它甚至可能不会花费任何成本。作为起点,您可以查看 TinyPNG - https://tinypng.com/。他们有一个开发者 API - https://tinypng.com/developers。

编辑:根据有关音量的新信息,更新我的答案。 由于您期望的图像数量很少,因此您可以只使用 TinyPNG。上手非常简单。您只需注册,即可获得 API 密钥。他们有一个很好的 API,你可以在 Java 中使用 - https://tinypng.com/developers/reference/java

【讨论】:

用户从他的画廊或相机中选择一张照片,然后当他点击保存按钮时,图像大小必须减小,例如从 4Mb 到(最大 500 Kb)并将图像上传到存储 @MohamedYacineZouaoui 好的,你期待什么样的音量?比如你每个月会做多少次压缩(结合所有用户)? 它可以在 25 到 40 之间! @MohamedYacineZouaoui 更新了我的答案,如果它解决了您的问题,请告诉我【参考方案2】:

我也在尝试解决这个问题,但似乎没有其他方法对我们的情况有直接帮助。

“可能重复”示例仅在您将图像转换为位图时才有效。几乎所有您尝试使用位图实现的示例。这是该“重复”中的一些代码,应该可以帮助您。虽然在我实现了这个之后,我在处理轮换方面遇到了麻烦。

Uri selectedImageUri = data.getData();

Bitmap bmp = null;
try 
    bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImageUri);
  catch (IOException e) 
    e.printStackTrace();
 
  ByteArrayOutputStream baos = new ByteArrayOutputStream();

 //here you can choose quality factor in third parameter(ex. i choosen 25) 
 bmp.compress(Bitmap.CompressFormat.JPEG, 25, baos);
 byte[] fileInBytes = baos.toByteArray();

 StorageReference photoref = chatPhotosStorageReference.child(selectedImageUri.getLastPathSegment());

 //here i am uploading
 photoref.putBytes(fileInBytes).addOnSuccessListener....etc

虽然这可能是正确的答案。我自己更喜欢更简洁的解决方案,它允许我通过 InputStream 或 Uri 压缩文件,因为这也是我将图像上传到 Firebase 存储的方式。

我可能会这样做并直接处理位图,但如果可以的话,我打算寻找替代解决方案。

要添加这个extension with firebase,它会在您上传后调整大小

【讨论】:

以上是关于如何在将图像上传到 Firebase 存储之前对其进行压缩?的主要内容,如果未能解决你的问题,请参考以下文章

如何在将照片上传到 Firebase 存储时将日期或时间等用户图像详细信息添加到文件名?

是否有必要在将聊天消息存储到 Firebase 之前对其进行加密?

Flutter - 将图像上传到 Firebase 存储

如何在上传到 Firebase 存储之前压缩 Expo 中的视频?

如何从输入字段将图像上传到 Firebase 云存储?

在上传到 Firebase 存储之前,您是不是必须知道图像文件类型?