当前位置:   article > 正文

Android不通过oss-android-sdk,直接访问阿里云OSS_如何在android里连接并使用阿里云的oss服务器

如何在android里连接并使用阿里云的oss服务器

场景

自开发一个Android APP,只有自己一个人进行使用,想直接从OSS上下载文件做解析,但是阿里云提供给Android的SDK,必须要通过STS的嫁接,

即必须要有一台服务器,用于获取token,其不推荐由APP直接使用ACCESS_KEY_ID与ACCESS_KEY_SECRET直接对OSS进行访问,因为认为APP是不安全的,

但是对于这种私人使用的,apk仅安装在自己手机上的,还需要一台服务器的嫁接,未免有成本所在,

不论是服务端的SDK还是Android的SDK,本质都是最终拼接一些参数,使用HTTP协议发送过去,因此只需要了解需要发送哪些参数可以正确读到资源就好,

我的业务是读取资源:GetObject - 对象存储 OSS - 阿里云

如下图可以看到,读取一个资源本质就是发起一个get请求,同时在Http Header头部带上Host、Date、Authorization。

 阿里云的HTTP协议文档:使用REST API发起请求 - 对象存储 OSS - 阿里云

Authorization的签名方式:

我在经过对url、Date、Authorization的调参后,成功使用PostMan下载到了文件,由此可以说明,我们在Android中也可以通过一样的方式去下载到OSS中的文件。

最终实现

如果要手动编码,需要很多东西,因此我还是依赖了阿里提供给Server端的SDK,用作签名使用,发起Http请求则是使用的OkHTTP3,

为什么不用HttpClient?因为我本以为直接用阿里给Server端的SDK也就是aliyun-sdk-oss可以直接请求,却发现在Android中报错如下:

  1. No static field INSTANCE of type Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier;
  2. in class Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier;
  3. or its superclasses (declaration of 'org.apache.http.conn.ssl.AllowAllHostnameVerifier' appears in /system/framework/framework.jar!classes3.dex)

最终看到一个老外说,该库可能并不是提供给Android端使用的,虽然看错误是某个字段不存在,貌似framework中内置该jar,因为先加载的是framework.jar中的,所以aliyun-sdk-oss内置的httpclient不会被加载,

这个问题我最终没有找出来,因此姑且认为aliyun-sdk-oss真的没法在Android端使用,当然如果读者可以解决这个库在Android上的这个问题,那么aliyun-sdk-oss就可以直接使用,没必要自己手写API对接OSS这么麻烦,有解决方法也请告诉我。

下面,我依赖的两个库:

  1. implementation 'com.aliyun.oss:aliyun-sdk-oss:3.15.1'
  2. implementation 'com.squareup.okhttp3:okhttp:4.10.0'

实现代码:

需要注意的是,这里需要你改的几个地方:BUCKET、END_POINT、ACCESS_KEY_ID、ACCESS_KEY_SECRET,这几个字段请改成你自己阿里云OSS的配置。

  1. private static final String BUCKET = "your bucket";
  2. private static final String END_POINT = "your end point";
  3. private static final String ACCESS_KEY_ID = "your ACCESS_KEY_ID";
  4. private static final String ACCESS_KEY_SECRET = "your ACCESS_KEY_SECRET";
  5. private static final String DATE = "Date";
  6. private static final String AUTHORIZATION = "Authorization";
  7. private static String getEndPoint() {
  8. return "https://" + BUCKET + "." + END_POINT;
  9. }
  10. private static String getEndPoint(String aliFileName) {
  11. return getEndPoint() + "/" + aliFileName;
  12. }
  13. private static String getResourceName(String aliFileName) {
  14. return "/" + BUCKET + "/" + aliFileName;
  15. }
  16. private static String getGmtTime() {
  17. Calendar cd = Calendar.getInstance();
  18. SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
  19. sdf.setTimeZone(TimeZone.getTimeZone("GMT")); // 设置时区为GMT
  20. return sdf.format(cd.getTime());
  21. }
  22. public void downloadFile(String aliFileName) {
  23. String nowTime = getGmtTime();
  24. HashMap<String, String> map = new HashMap<>();
  25. map.put(DATE, nowTime);
  26. RequestMessage requestMessage = new RequestMessage(BUCKET, aliFileName);
  27. requestMessage.setBucket(BUCKET);
  28. requestMessage.setKey(aliFileName);
  29. requestMessage.setResourcePath(aliFileName);
  30. requestMessage.setMethod(HttpMethod.GET);
  31. requestMessage.setEndpoint(URI.create(getEndPoint()));
  32. requestMessage.setHeaders(map);
  33. String signature = SignUtils.buildSignature(ACCESS_KEY_SECRET, HttpMethod.GET.name(), getResourceName(aliFileName), requestMessage);
  34. String authorization = SignUtils.composeRequestAuthorization(ACCESS_KEY_ID, signature);
  35. Map<String, String> getHeaders = new LinkedHashMap<>();
  36. getHeaders.put(DATE, nowTime);
  37. getHeaders.put(AUTHORIZATION, authorization);
  38. File file = new File(this.getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), aliFileName);
  39. download(getEndPoint(aliFileName), file, getHeaders);
  40. }
  41. public static void download(String url, File file, Map<String, String> headers) {
  42. new Thread(() -> {
  43. try {
  44. OkHttpClient client = new OkHttpClient();
  45. Request.Builder requestBuilder = new Request.Builder().url(url);
  46. for (String key : headers.keySet()) {
  47. requestBuilder.addHeader(key, headers.get(key));
  48. }
  49. Request request = requestBuilder.build();
  50. Response response = client.newCall(request).execute();
  51. InputStream inputStream;
  52. inputStream = response.body().byteStream();
  53. RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
  54. randomAccessFile.seek(0);
  55. byte[] buf = new byte[1024];
  56. int len;
  57. while ((len = inputStream.read(buf)) != -1) {
  58. randomAccessFile.write(buf, 0, len);
  59. }
  60. response.body().close();
  61. randomAccessFile.close();
  62. } catch (Exception ex) {
  63. ex.printStackTrace();
  64. System.err.println(ex);
  65. }
  66. }).start();
  67. }

最终使用,调用一下downloadFile,传入你在OSS中的文件名就好,下载好的文件会存到你的APP的downloads文件夹下:

最终请确认你的app开启了文件读写权限,以及网络访问权限:

  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  2. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  3. <uses-permission android:name="android.permission.INTERNET"/>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/624391
推荐阅读
相关标签
  

闽ICP备14008679号