Android SDK 28及以上如何通过Nextcloud API用HTTP PUT请求上传文件
SDK版本相关说明
不需要更换SDK版本。Android 10(API 29)引入的分区存储机制确实限制了第三方应用直接获取公共目录下文件的真实路径,降级到API 28及以下虽然可以绕过该限制,但目前主流应用商店要求应用targetSdk版本不低于33,降级会导致无法正常上架,无实际意义。
你之前遇到的CursorWindow: Failed to read row 0, column -1报错,是因为旧版获取路径的方案查询的MediaStore列名在高版本Android中不存在,返回了无效列索引,该方案在API 29及以上版本已经完全不可用,无需再尝试。
路径问题可以通过两种方案解决:
- 将选中Uri对应的文件转存到应用专属沙盒目录(应用cache目录或外部存储专属files目录),沙盒内的文件可以直接获取绝对路径,传给Nextcloud官方库即可,用完可删除临时文件避免占用空间
- 绕过官方库直接通过文件流上传,不需要获取本地绝对路径
转存临时文件示例代码:
// 将Uri转为应用沙盒内的临时文件,可直接获取绝对路径 public File getTempFileFromUri(Context context, Uri uri, String fileName) throws IOException { File tempFile = new File(context.getCacheDir(), fileName); try (InputStream is = context.getContentResolver().openInputStream(uri); FileOutputStream fos = new FileOutputStream(tempFile)) { byte[] buffer = new byte[4096]; int len; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } } return tempFile; }
手动填写路径有效性说明
你提供的storage/emulated/0/Pictures/IMG_20210829_151952_1.jpg不是完整的绝对路径,缺少了根目录前缀斜杠,正确的绝对路径应为/storage/emulated/0/Pictures/IMG_20210829_151952_1.jpg。你之前手动传入路径后上传失败,就是因为路径不完整导致本地文件读取失败,PUT请求未携带有效文件内容,因此Nextcloud服务器没有生成对应文件。
绕过官方库实现WebDAV上传说明
完全可以绕过Nextcloud官方Android库自行实现WebDAV上传,且该方案更适配高版本Android的分区存储规则,不需要获取本地文件绝对路径,实现逻辑和你测试成功的curl命令一致:
- 拿到选中文件的Uri后,直接通过
ContentResolver.openInputStream(uri)获取文件输入流 - 使用OkHttp等网络库发起PUT请求,请求地址规则和curl测试地址一致,为
http://你的域名/remote.php/dav/files/用户名/远程文件名 - 请求头添加Basic Auth鉴权信息:将账号密码拼接为
用户名:密码格式后做Base64编码,添加请求头Authorization: Basic <编码后字符串> - 将文件输入流作为PUT请求的请求体传入,可自行实现上传进度监听
内容的提问来源于stack exchange,提问作者tschlueter
相关产品推荐
相关产品推荐

