android上传多张图片

本文介绍如何使用Retrofit结合RxJava实现多张图片的上传功能,涵盖图片压缩处理及多图上传的代码实现。

项目中有一个功能:发帖。

帖子内容:文字,图片(可以是多张)。这就涉及到多张图片的上传问题。

后台接口文档如下:

使用Retrofit+Rxjava上传多张图片的代码如下:

/**
 * 上传多张图片(带参数)
 */
public void uploadMoreImage2(RetrofitSubscriber<BaseRspBean<ImageUploadBean>> subscriber, List<File> imageFileList){
    List<MultipartBody.Part> photos = new ArrayList<>(imageFileList.size());
    //上传图片时携带参数,这里用于区分是帖子图片还是其他图片,比如头像等
    RequestBody imageType = RequestBody.create(MediaType.parse("text/plain"), "post");
    MultipartBody.Part body = MultipartBody.Part.createFormData("type",null, imageType);
    photos.add(body);
    //文件(注意与上面的不同)
    if(imageFileList != null && !imageFileList.isEmpty()) {
        for (File file:imageFileList){
            RequestBody photoRequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
            MultipartBody.Part part= MultipartBody.Part.createFormData("files", file.getName(), photoRequestBody);
            photos.add(part);
        }
    }
    RetrofitUtil.toSubscribe(getServiceOutHead(UrlConfig.BASEURL).uploadMoreImage2(HeaderHelper.getFileUpdateHeader(),photos),mContext, subscriber);
}

 

当然了,上传的图片需要经过压缩处理才能上传。(我们的图片是从本地相册选择的或者是拍照所得的)

压缩方法:

 

Bitmaputils.java
/**
 * 图片压缩-质量压缩
 *
 * @param filePath 源图片路径
 * @return 压缩后的路径
 */

public static String compressImage(String filePath) {
    //原文件
    File oldFile = new File(filePath);
    //压缩文件路径 照片路径/
    String targetPath = oldFile.getPath();
    int quality = 50;//压缩比例0-100
    Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片
    int degree = getRotateAngle(filePath);//获取相片拍摄角度
    if (degree != 0) {//旋转照片角度,防止头像横着显示
        bm = setRotateAngle(degree,bm);
    }
    File outputFile = new File(targetPath);
    try {
        if (!outputFile.exists()) {
            outputFile.getParentFile().mkdirs();
        }
        FileOutputStream out = new FileOutputStream(outputFile);
        bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
        return filePath;
    }
    return outputFile.getPath();
}

/**
 * 根据路径获得图片信息并按比例压缩,返回bitmap
 */
public static Bitmap getSmallBitmap(String filePath) {
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;//只解析图片边沿,获取宽高
    BitmapFactory.decodeFile(filePath, options);
    // 计算缩放比
    options.inSampleSize = calculateInSampleSize(options, 480, 800);
    // 完整解析图片返回bitmap
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(filePath, options);
}

public static int calculateInSampleSize(BitmapFactory.Options options,
                                        int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

/**
 * 旋转图片角度
 *
 * @param angle
 * @param bitmap
 * @return
 */
public static Bitmap setRotateAngle(int angle, Bitmap bitmap) {

    if (bitmap != null) {
        Matrix m = new Matrix();
        m.postRotate(angle);
        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), m, true);
        return bitmap;
    }
    return bitmap;
}

以上就是上传多张图片的逻辑。

要在 Android 中实现上传多张图片并限制为 9 张,可按以下步骤进行。 ### 1. 界面布局 在布局文件里设置一个 `RecyclerView` 来展示所选图片,添加一个按钮用于触发图片选择操作。 ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="wrap_content"/> <Button android:id="@+id/selectImagesButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Select Images"/> </LinearLayout> ``` ### 2. 选择图片 借助 `Intent` 开启系统相册选择图片,同时使用 `ActivityResultLauncher` 处理选择结果。 ```java import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private ImageAdapter imageAdapter; private List<Uri> selectedImages = new ArrayList<>(); private ActivityResultLauncher<Intent> imagePickerLauncher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); imageAdapter = new ImageAdapter(selectedImages); recyclerView.setAdapter(imageAdapter); Button selectImagesButton = findViewById(R.id.selectImagesButton); selectImagesButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); imagePickerLauncher.launch(intent); } }); imagePickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == RESULT_OK) { Intent data = result.getData(); if (data != null) { if (data.getClipData() != null) { int count = data.getClipData().getItemCount(); for (int i = 0; i < count; i++) { if (selectedImages.size() < 9) { Uri imageUri = data.getClipData().getItemAt(i).getUri(); selectedImages.add(imageUri); } } } else if (data.getData() != null) { if (selectedImages.size() < 9) { Uri imageUri = data.getData(); selectedImages.add(imageUri); } } imageAdapter.notifyDataSetChanged(); } } } }); } } ``` ### 3. 图片适配器 创建一个 `RecyclerView.Adapter` 用于展示所选图片。 ```java import android.net.Uri; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.List; public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder> { private List<Uri> images; public ImageAdapter(List<Uri> images) { this.images = images; } @NonNull @Override public ImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false); return new ImageViewHolder(view); } @Override public void onBindViewHolder(@NonNull ImageViewHolder holder, int position) { Uri imageUri = images.get(position); holder.imageView.setImageURI(imageUri); } @Override public int getItemCount() { return images.size(); } public static class ImageViewHolder extends RecyclerView.ViewHolder { ImageView imageView; public ImageViewHolder(@NonNull View itemView) { super(itemView); imageView = itemView.findViewById(android.R.id.text1); } } } ``` ### 4. 图片上传 选择好图片后,可使用 `OkHttp` 或 `Volley` 等网络库将图片上传至服务器。 ```java import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import java.io.File; import java.io.IOException; public class ImageUploader { public static void uploadImages(List<Uri> imageUris) { OkHttpClient client = new OkHttpClient(); MultipartBody.Builder builder = new MultipartBody.Builder() .setType(MultipartBody.FORM); for (Uri uri : imageUris) { File file = new File(uri.getPath()); RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file); builder.addFormDataPart("image", file.getName(), requestBody); } MultipartBody requestBody = builder.build(); Request request = new Request.Builder() .url("YOUR_UPLOAD_URL") .post(requestBody) .build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { // 上传成功 } else { // 上传失败 } } catch (IOException e) { e.printStackTrace(); } } } ``` 在上传图片时,可参考引用[1]中提到的优化技术,如图片大小限制与异步处理,以提升上传体验。对于图片大小限制,可防止因图片过大导致内存溢出问题,像引用[2]中所描述的情况。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值