Android开发:打开相册选择照片后上传到阿里云OSS(对象存储)

引入:在前几篇文章中,分别讲解了如何调用摄像头、如何拍摄视频并上传到阿里云,本篇文章将分享如何通过相册选择图片并上传到阿里云。
在这里插入图片描述
文章一:Android开发:调用摄像头拍摄照片后上传到阿里云OSS(对象存储)
文章二:Android开发:Camera2+MediaRecorder录制视频后上传到阿里云VOD
本篇文章:Android开发:打开相册选择照片后上传到阿里云OSS(对象存储)
上述三篇文章可以实现如图所示的功能即通过拍照、相册、录制视频上传到服务器


前言:startActivityForResult与onActivityResult详解

提示:startActivityForResult 和 onActivityResult 这两个方法在 Android 开发中已经被标记为过时(deprecated)。

对于 startActivityForResult 的过时,官方推荐的替代方案是使用 registerForActivityResult。这个方法提供了一种更现代、更灵活的方式来处理从其他活动返回的结果。registerForActivityResult 允许你注册一个 ActivityResultLauncher,并通过它启动活动并处理返回的结果。这种方式的好处是减少了代码的嵌套和耦合,使得代码更加清晰和易于维护。

目前本文中使用的仍然是startActivityForResult与onActivityResult,下面对其进行详细的解释:

startActivityForResult 和 onActivityResult 是 Android 开发中用于从一个活动(Activity)启动另一个活动,并期望从第二个活动返回一些结果到第一个活动的机制。这在多种场景下都非常有用,比如启动一个相机应用来拍照并返回图片,或者启动一个选择器来选择文件等。

startActivityForResult

startActivityForResult 方法用于启动一个新的活动,并期望该活动结束时返回结果。这个方法接受两个参数:

Intent:一个 Intent 对象,描述了要启动的活动的详细信息。
Request Code:一个整数,用于标识这次启动活动的请求。当结果返回时,这个请求码用于区分不同的启动请求。
示例:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
startActivityForResult(intent, REQUEST_CODE_CAPTURE_IMAGE);

在这个示例中,我们启动了一个相机应用来拍照。REQUEST_CODE_CAPTURE_IMAGE 是一个常量,用于标识这个特定的启动请求。

onActivityResult

onActivityResult 方法是一个回调方法,当启动的活动结束时,系统会调用这个方法,并将结果传递回来。这个方法接受三个参数:

1.Request Code:与 startActivityForResult 中的请求码相对应,用于区分不同的启动请求。
2.Result Code:一个整数,表示启动的活动结束时的状态。通常是 RESULT_OK 或RESULT_CANCELED。
3.Data:一个 Intent 对象,包含了从启动的活动返回的数据。

@Override  
protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    super.onActivityResult(requestCode, resultCode, data);  
    if (requestCode == REQUEST_CODE_CAPTURE_IMAGE && resultCode == RESULT_OK) {  
        // 处理返回的数据  
    }  
}

在这个示例中,我们检查请求码和结果码来确定是否是我们期望的相机应用返回的结果,并处理返回的数据。

注意点
请求码:确保为每个 startActivityForResult 调用使用唯一的请求码,以便在 onActivityResult 中正确识别它们。
结果码:除了系统定义的 RESULT_OK 和 RESULT_CANCELED,你也可以定义自己的结果码来表示特定的状态。
安全性:由于 onActivityResult 可以从其他应用接收数据,因此应该谨慎处理返回的数据,以避免潜在的安全风险。
通过 startActivityForResult 和 onActivityResult,你可以实现从一个活动启动另一个活动,并在第二个活动完成后获取结果的功能,从而构建出更加丰富和交互性的 Android 应用。


一、实现打开相册并选择图片的功能

1.打开Android Studio新建一个Android 空项目 命名为Album
在这里插入图片描述
2.XML的编写,一个用来打开相册的按钮 一个可以放置图片的ImageView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:src="@mipmap/ic_launcher"
        tools:ignore="MissingConstraints" />
    <Button
        android:layout_gravity="center"
        android:id="@+id/open_album"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="打开相册"
        tools:ignore="MissingConstraints" />

</LinearLayout>

效果:
在这里插入图片描述

MainActivity中的代码:

package com.example.album;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    Uri imageUri;
    private Button button;
    private ImageView imageView;
    private static int key=1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=findViewById(R.id.open_album);
        imageView=findViewById(R.id.image_view);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.open_album:
                Intent intent=new Intent(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent,key);
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode==key){
            imageUri = data.getData();
            imageView.setImageURI(imageUri);
        }
    }
}

效果:
打开相册:
在这里插入图片描述
2.点击选中照片:
在这里插入图片描述

二、上传到阿里云对象存储(OSS)

提示:此处与其他两篇文章不同的是:这里最终获得的对象是一个Uri、而另外两篇文章有文件的准确路径,那么怎么处理Uri是第一个要考虑的问题:这里是将这个Uri转化成了Byte数组后进行上传。
1.测试阿里云官方文档的方法:
在这里插入图片描述
在这里插入图片描述
测试通过后
改写这段代码在SpringBoot工程上:
Controller层:

//处理字节数组的API
    @PostMapping("/uploadByte")
    public Map<String,Object> uploadByteImage(@RequestBody byte[] data){
        String url=ossService.uploadByteFile(data);
        HashMap<String, Object> map = new HashMap<>();
        map.put("code",0);
        map.put("data",url);
        map.put("messsage","成功");
        return map;

    }

Service层:

public interface OssFileService {
    String uploadByteFile(byte[] data);
}

Impl层:

 @Override
    public String uploadByteFile(byte[] data) {
        String endpoint= "你的endpoint";
        String accessKeyId="你的accessKeyId";
        String accessKeySecret="你的accessKeySecret";
        String bucketName= "你的bucketName";
        OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);
        String s1 = new DateTime().toString("yyyy/MM/dd");
        String filename="example.png";
        String objectname=s1+"/"+filename;
        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectname, new ByteArrayInputStream(data));
            PutObjectResult result = ossClient.putObject(putObjectRequest);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        String url = "https://" + bucketName + "." + endpoint + "/" + filename;
        return url;
    }

上述代码中的四个常量都可以在官网中相应的获取 前文Android开发:调用摄像头拍摄照片后上传到阿里云OSS(对象存储)里面详细解释这里不做赘述(依赖的引入、Bucket的创建等等都涵盖)

三、在Android中用第三方库Okhttp请求服务端API

1.添加Okhttp依赖:

    implementation 'com.squareup.okhttp3:okhttp:4.4.1'
    implementation 'org.conscrypt:conscrypt-android:2.2.1'

在这里插入图片描述
2.添加网络权限:

<uses-permission android:name="android.permission.INTERNET"/>

在这里插入图片描述
3.更改MainActivity中的代码:

package com.example.album;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final MediaType MEDIA_TYPE_OCTET_STREAM = MediaType.parse("application/octet-stream");
    Uri imageUri;
    private Button button;
    private ImageView imageView;
    private static int key=1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=findViewById(R.id.open_album);
        imageView=findViewById(R.id.image_view);
        button.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.open_album:
                Intent intent=new Intent(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent,key);
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode==key){
            imageUri = data.getData();
            try {
                ContentResolver contentResolver = getContentResolver();
                InputStream inputStream = contentResolver.openInputStream(imageUri);
                // 读取输入流内容到字节数组
                byte[] fileBytes = readFullyToByteArray(inputStream);
                OkHttpClient client=new OkHttpClient();
                RequestBody requestBody = RequestBody.create(MEDIA_TYPE_OCTET_STREAM, fileBytes);
                Request request = new Request.Builder()
                        .url("你的Ip地址:你的端口号/oss/files/uploadByte")
                        .post(requestBody)
                        .build();
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(@NonNull Call call, @NonNull IOException e) {
                    }
                    @Override
                    public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(getBaseContext(),"图片上传成功",Toast.LENGTH_SHORT).show();
                                imageView.setImageURI(imageUri);
                            }
                        });
                    }
                });
                // 现在你可以使用inputStream来读取文件内容
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private byte[] readFullyToByteArray(InputStream inputStream)
    {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try
        {
            byte[] buffer = new byte[4096];
            // 缓冲区大小,可以根据需要调整
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outputStream.toByteArray();
    }
}

效果:
在这里插入图片描述

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
public class GetAndUploadFileDemo { private static String TAG = "GetAndUploadFileDemo"; private OSSService ossService; private OSSBucket bucket; public void show() { ossService = OSSServiceProvider.getService(); bucket = ossService.getOssBucket("youcaidao"); // 文件的常规操作如普通上传、下载、拷贝、删除等,与Data类一致,故这里只给出断点下载和断点上传的demo resumableDownloadWithSpecConfig(); // delay(); // resumableUpload(); // delay(); // resumableDownload(); // delay(); } public void delay() { try { Thread.sleep(30 * 1000); } catch (Exception e) { e.printStackTrace(); } } // 断点上传 public void resumableUpload() { // OSSData ossData = ossService.getOssData(sampleBucket, "sample-data"); // ossData.setData(data, "raw"); // 指定需要上传的数据和它的类型 // ossData.enableUploadCheckMd5sum(); // 开启上传MD5校验 // ossData.upload(); // 上传失败将会抛出异常 OSSFile bigfFile = ossService.getOssFile(bucket, "de.jpg"); try { bigfFile.setUploadFilePath( "/storage/emulated/0/Android/data/com.qd.videorecorder/video/VMS_1439866564822.jpg", "image/jpg"); bigfFile.ResumableUploadInBackground(new SaveCallback() { @Override public void onSuccess(String objectKey) { Log.d(TAG, "[onSuccess] - " + objectKey + " upload success!"); } @Override public void onProgress(String objectKey, int byteCount, int totalSize) { Log.d(TAG, "[onProgress] - current upload " + objectKey + " bytes: " + byteCount + " in total: " + totalSize); } @Override public void onFailure(String objectKey, OSSException ossException) { Log.e(TAG, "[onFailure] - upload " + objectKey + " failed!\n" + ossException.toString()); ossException.printStackTrace(); ossException.getException().printStackTrace(); } }); } catch (FileNotFoundException e) { e.printStackTrace(); } } // 断点下载 public void resumableDownload() { OSSFile bigFile = ossService.getOssFile(bucket, "bigFile.dat"); bigFile.ResumableDownloadToInBackground( "/storage/sdcard0/src_file/bigFile.dat", new GetFileCallback() { @Override public void onSuccess(String objectKey, String filePath) { Log.d(TAG, "[onSuccess] - " + objectKey + " storage path: " + filePath); } @Override public void onProgress(String objectKey, int byteCount, int totalSize) { Log.d(TAG, "[onProgress] - current download: " + objectKey + " bytes:" + byteCount + " in total:" + totalSize); } @Override public void onFailure(String objectKey, OSSException ossException) { Log.e(TAG, "[onFailure] - download " + objectKey + " failed!\n" + ossException.toString()); ossException.printStackTrace(); } }); } // 设置相关参数的断点续传 public void resumableDownloadWithSpecConfig() { OSSFile bigFile = ossService .getOssFile(bucket, "VMS_1439866564822.jpg"); ResumableTaskOption option = new ResumableTaskOption(); option.setAutoRetryTime(2); // 默认为2次,最大3次 option.setThreadNum(2); // 默认并发3个线程,最大5个 bigFile.ResumableDownloadToInBackground( "/storage/emulated/0/Android/data/com.qd.videorecorder/video/VMS_1439866564822.jpg", new GetFileCallback() { // /storage/emulated/0/DCIM/Camera/VID_20150803_173350.mp4 @Override public void onSuccess(String objectKey, String filePath) { System.out.println("[onSuccess] - " + objectKey + " storage path: " + filePath); } @Override public void onProgress(String objectKey, int byteCount, int totalSize) { System.out.println("[onProgress] - current download: " + objectKey + " bytes:" + byteCount + " in total:" + totalSize); } @Override public void onFailure(String objectKey, OSSException ossException) { System.out.println("[onFailure] - download " + objectKey + " failed!\n" + ossException.toString()); ossException.printStackTrace(); } }); } }
SpringBoot可以通过整合阿里云OSS对象存储服务来实现文件上传和管理功能。具体实现可以参考以下步骤: 1. 在service层定义FileService接口,该接口包含上传文件到阿里云OSS的方法。例如,可以使用MultipartFile作为参数,返回上传成功后的文件URL。 2. 在controller层编写FileApiController类,该类使用@RestController注解标识为控制器,并使用@RequestMapping注解指定请求路径。在该类中,通过@Autowired注入FileService,并在文件上传的接口方法中调用FileService的上传文件方法并返回上传成功后的文件URL。 3. 在配置文件中配置阿里云OSS的相关信息,包括accessKey、secretKey、bucketName等。可以使用SpringBoot提供的@ConfigurationProperties注解来读取配置文件中的信息。 4. 在pom.xml文件中添加阿里云OSS SDK的依赖。 5. 编写上传文件的前端界面,可以使用HTML或者前端框架如Vue.js、React等。 通过以上步骤的实现,SpringBoot就可以整合阿里云OSS对象存储服务,实现文件上传和管理功能。这样可以将文件存储在阿里云OSS中,提高文件的安全性和可靠性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot整合阿里云OSS对象存储服务的实现](https://download.csdn.net/download/weixin_38649091/12721580)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [全网最详细SpringBootSpringCloud整合阿里云OSS对象存储服务](https://blog.csdn.net/weixin_55076626/article/details/127924003)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值