【安卓开发之图片分享应用5:上传图片到服务器】

  • Post author:
  • Post category:其他





开发过程中遇到的问题



1、W/System.err: java.net.UnknownServiceException:


报错

W/System.err: java.net.UnknownServiceException: 
CLEARTEXT communication to xxx.xxx.xxx not permitted by network security policy


问题分析:

为保证用户数据和设备的安全,Google针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量,未来都不能明码传输,需要使用下一代(Transport Layer Security)传输层安全协议,而 Android Nougat 和 Oreo 则不受影响。

在Android P系统的设备上,如果应用使用的是非加密的明文流量的http网络请求,则会导致该应用无法进行网络请求,https则不会受影响,同样地,如果应用嵌套了webview,webview也只能使用https请求。


解决方法:往

AndroidManifest



application

中设置下列属性即可。

android:usesCleartextTraffic="true"

在这里插入图片描述




一、效果演示


这次主要是实现本地图片上传到服务器的功能,如下

gif

所示:上传图片之后,就可以通过图片链接来访问到图片,并在页面展示出来。

在这里插入图片描述

上传成功之后可以在服务器查看到该图片了,如下图所示:

在这里插入图片描述




二、购买阿里云OSS对象存储


直接在阿里云首页搜索

对象存储OSS

在这里插入图片描述


点击

图中所示的地方

在这里插入图片描述


我们选择

标准存储包

即可,然后选择

中国大陆

地区,存储包规格选个

40G

够用了,因为只是存储博客图片,或者是笔记图片都是够了的。然后时长按自己所需来选即可,反正也不贵。流量的话因为我就上次一点图片,所以按量计费不是很贵。


(咳咳,存储空间虽然不贵,但是外网访问图片资源时下载图片资源不免费,这是真滴坑,值得一提的是上传图片免费,具体可以查看相关资料)

在这里插入图片描述




三、设置阿里云OSS对象存储配置



1. 新建Bucket

在这里插入图片描述



2. 配置Bucket


按图中选择即可,因为我也是服务器小白,所以某些设置可能有问题,但是毕竟这只是一个学习的demo,设置好Bucket之后能使用就行,是吧,嘿嘿嘿…

在这里插入图片描述


然后点击进入该

Bucket

,创建几个存放图片的文件夹,这里我创建了一个存放头像的文件夹

usericons

,以及创建一个存放用户发布的图片的文件夹

images

在这里插入图片描述



3. 绑定域名(如果有)


如果有域名且域名认证了的话,可以绑定域名。没有就跳过这一步即可。


在这里插入图片描述

这里可能会有一个问题:

添加 CNAME 记录提示和 A 记录冲突如何解决



解决方法:

添加 CNAME 记录提示和 A 记录冲突解决方法

在这里插入图片描述



4. 创建RAM用户获取密匙


点击

AccessKey管理

在这里插入图片描述


点这个


在这里插入图片描述


创建一个Ram用户


在这里插入图片描述


创建好之后点击确认,名称随便填


在这里插入图片描述


经过验证之后就创建成功了记得要保存

AccessKey ID



AccessKey Secret

, 不保存下次就没了,没了能怎么办?重新删掉,再创建一个呗!!!


在这里插入图片描述


给创建的Ram用户赋值, 在用户界面, 点击添加权限


在这里插入图片描述


最后赋予图中的权限, 点击确认即可, 这样就完成了配置, 完成了之后我们就需要到代码中去配置了。


(其实这样也是完成了图床的配置, 可以使用我们获取到的

AcessKeyID



AcessKey Secret



PicGo

软件上配置,这样随时都能上传图片到该服务器, 还可以配合

Typora

将写笔记(博客)的图片上传到该服务器,这里就不写了).

在这里插入图片描述




四、Android上传到服务器代码实现

参考文献:


阿里云官网:


上传本地文件到阿里云OSS



1. 引入阿里云OSS依赖

//自动获取最新版本
implementation 'com.aliyun.dpa:oss-android-sdk:+'



2. AliyunUploadFile工具类


这个就是我们上传图片封装的工具类了。我已经写好注释了,你只需要将你的

AccessKey ID



AcessKey Secert

等填好,在图片发布Activity中调用该类,将获取到的图片地址传到该类就行了。

public class AliyunUploadFile {

    private OSSCredentialProvider credentialProvider;

    private ClientConfiguration conf;

    private OSS oss;

    // 填写生成的访问密钥AccessKey ID和AccessKey Secret。
    private String AccessKeyId = "LTAI66GDnSkpScpuJMgt26RJ";
    private String SecretKeyId = "U8eEfIlz4f7DTP8hjW4b8FfFUBBxtA";
    // STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。
    private String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
    //bucketName
    private String bucketName = "xiaohaituchuang";


    /**
     *
     * @param context 上下文
     * @param uploadFilePath 上传的文件路径
     */
    public void UploadFile(Context context, String uploadFilePath) {

        // 第一个参数:在【RAM访问控制】创建用户时分配的accessKeyId
        // 第二个参数:在【RAM访问控制】创建用户时分配的accessKeySecret
        OSSCredentialProvider ossCredentialProvider = new OSSPlainTextAKSKCredentialProvider(AccessKeyId, SecretKeyId);

        // 第一个参数:上下文
        // 第二个参数:在OSS控制台创建好Bucket后,会有一个EndPoint(地域节点),比如我这里的节点是:http://oss-cn-hangzhou.aliyuncs.com
        // 第三个参数:OSSCredentialProvider
        OSS oss = new OSSClient(context.getApplicationContext(), endpoint, ossCredentialProvider);


        String img_name = "images/img_";
  


        //获取图片格式后缀名,比如.png, .jpg等等
        String str1 = uploadFilePath.substring(0, uploadFilePath.indexOf("."));
        String str2 = "." + uploadFilePath.substring(str1.length()+1,uploadFilePath.length());


        //上传后图片的地址, 可以将该图片地址存入数据库,我这里就不写存进数据库了。
        String img_url = "http://域名/" + img_name + str2;
        img_name = img_name + str2;


        // 第二个参数:可以是一个文件路径:比如你在xiaohaituchuang创建了一个文件夹为images,那第二个参数传images/img.jpg
        // 第三个参数:是文件的本地路径,比如我这里在本地路径中是姨丈图片,路径是sdcard/img/img.jpg
        PutObjectRequest put = new PutObjectRequest(bucketName, img_name, uploadFilePath);
        // 异步上传时可以设置进度回调。
        put.setProgressCallback((request, currentSize, totalSize) -> {
            Log.d("currentSize = " + currentSize, "totalSize = " + totalSize);
        });
        // 此处调用异步上传方法
        OSSAsyncTask ossAsyncTask= oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
            @Override
            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                Log.d("PutObject", "UploadSuccess");
                Log.d("ETag", result.getETag());
                Log.d("RequestId", result.getRequestId());
                uploadFlag = 1; //这个是上次多张图片时判断上传成功的标准,我在例子里写有,不需要的话可以删除

            }

            @Override
            public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                // 请求异常。
                if (clientException != null) {
                    // 本地异常,如网络异常等。
                    Log.e("网络异常",clientException.getMessage());
                    uploadFlag = 2;
                }
                if (serviceException != null) {
                    // 服务异常。
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                    uploadFlag = 3;
                }
            }
        });
    }
}



3. AliyunUploadFile工具类调用小例子,可一次上次多张图片


我这里就简单的对发布按钮进行监听, 当点击的时候调用上传文件工具类对图片进行上传。在

NineGridViewActivity

里面编写:


(1)定义图片集合

private List<File> files; //图片集合
private int[] filesIndex; //图片集合下标


(2)定义图片上传状态:

public static int uploadFlag = 0;   //0:表示图片未开始上传,  1:表示图片上传成功


(3)初始化图片集合




OnCreate

方法里面初始化即可。

files = new ArrayList<>();
filesIndex = new int[9];//因为我弄的是最多9张图


(4)获取图片地址。

for (int i = 0; i < list.size(); i++) {
    File file = new File(list.get(i).getImagePath());
    files.add(file);
    filesIndex[i] = 1;
}

在这里获取图片地址:

在这里插入图片描述


(5)调用工具类,点击发布按钮后,就上传。

这里演示的是在

NineGridViewActivity

中的

OnCreate

调方法用该工具类:


//绑定上传图片按钮
Button button = findViewById(R.id.send_button);
//监听按钮点击事件,点击后上传图片.
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        AliyunUploadFile picUpload = new AliyunUploadFile();

        Toast.makeText(NineGridViewActivity.this, "上传中,请稍后!!!", Toast.LENGTH_SHORT).show();


        //上传图片
        try {
            for (int i = 0; i < files.size(); i++) {
                if(filesIndex[i] != 1) continue;
                picUpload.UploadFile(NineGridViewActivity.this,files.get(i).getPath());
                //等待该图片上传完成
                while (uploadFlag == 0);
                if(i < files.size()-1) uploadFlag = 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //等待最后一张图上传完成
        while (uploadFlag == 0);

        //使用弹窗反馈给用户上传结果
        switch (uploadFlag) {
            case 1:
                Toast.makeText(NineGridViewActivity.this, "上传成功!!!", Toast.LENGTH_SHORT).show();
                break;
            case 2:
                Toast.makeText(NineGridViewActivity.this, "上传失败,网络异常!!!", Toast.LENGTH_SHORT).show();
                break;
            case 3:
                Toast.makeText(NineGridViewActivity.this, "上传失败,服务器异常!!!", Toast.LENGTH_SHORT).show();
                break;
            case 4:
                Toast.makeText(NineGridViewActivity.this, "上传失败,数据库异常!!!", Toast.LENGTH_SHORT).show();
                break;
            default:
                Toast.makeText(NineGridViewActivity.this, "上传失败,未知错误!!!", Toast.LENGTH_SHORT).show();
                break;
        }
    }
});


上传后的图片可以在服务器查看:


在这里插入图片描述


最后大功告成,在阿里云官网里控制台的对象存储OSS中可以看到上传的图片,谢谢大家的观看。



版权声明:本文为weixin_52785320原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。