Android Studio中向GraphQL服务器上传图片的方法及报错排查
Android GraphQL 文件上传:解决 ENOENT 错误
问题原因
从图库获取的 content:// 类型 Uri 并非直接对应本地文件路径,uri.toFile() 无法正确解析这类 Uri;再加上 Android 10+ 的分区存储限制,直接转换 File 必然触发“文件不存在”的错误。
解决方案
跳过 Uri 转 File 的步骤,直接通过 ContentResolver 获取文件流,用 DefaultUpload 构建上传对象——这是适配 Android 存储机制的正确方式。
实现代码
import android.content.ContentResolver import android.net.Uri import okio.buffer import okio.source import com.apollographql.apollo3.api.DefaultUpload // 从 Uri 构建 GraphQL Upload 对象 fun buildGraphQLUpload(contentResolver: ContentResolver, uri: Uri): DefaultUpload { // 获取文件名,从 ContentResolver 查询或使用默认值 val fileName = queryFileName(contentResolver, uri) ?: "uploaded_image.jpg" // 获取文件 MIME 类型,默认用 image/jpeg val mimeType = contentResolver.getType(uri) ?: "image/jpeg" return DefaultUpload.Builder() .fileName(fileName) .contentType(mimeType) .content { sink -> contentResolver.openInputStream(uri)?.use { inputStream -> inputStream.source().buffer().use { source -> sink.writeAll(source) } } ?: error("无法打开文件输入流") } .build() } // 辅助方法:从 ContentResolver 查询文件名 private fun queryFileName(contentResolver: ContentResolver, uri: Uri): String? { contentResolver.query(uri, null, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { val nameColumnIndex = cursor.getColumnIndex("_display_name") if (nameColumnIndex != -1) { return cursor.getString(nameColumnIndex) } } } return null }
使用方式
在图片选择回调中拿到 Uri 后,调用上述方法生成 DefaultUpload 对象,直接传入 GraphQL 请求的变量中即可。
注意事项
- Android 10 及以下需申请
READ_EXTERNAL_STORAGE权限;Android 11+ 通过系统图库选择图片时,无需额外申请权限。 - 确保处理权限请求逻辑,避免因权限缺失导致无法访问 Uri。
内容的提问来源于stack exchange,提问作者Rubyna Thapa
相关产品推荐
相关产品推荐

