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


开发过程中遇到的问题


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请求。



解决方法:往AndroidManifestapplication中设置下列属性即可。

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 IDAccessKey Secret, 不保存下次就没了,没了能怎么办?重新删掉,再创建一个呗!!!
在这里插入图片描述



给创建的Ram用户赋值, 在用户界面, 点击添加权限
在这里插入图片描述

最后赋予图中的权限, 点击确认即可, 这样就完成了配置, 完成了之后我们就需要到代码中去配置了。
(其实这样也是完成了图床的配置, 可以使用我们获取到的AcessKeyIDAcessKey SecretPicGo软件上配置,这样随时都能上传图片到该服务器, 还可以配合Typora将写笔记(博客)的图片上传到该服务器,这里就不写了).
在这里插入图片描述





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

参考文献:
阿里云官网:上传本地文件到阿里云OSS


1. 引入阿里云OSS依赖

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

2. AliyunUploadFile工具类

这个就是我们上传图片封装的工具类了。我已经写好注释了,你只需要将你的AccessKey IDAcessKey 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中可以看到上传的图片,谢谢大家的观看。

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值