Есть несколько связанных вопросов о выборе и загрузке файлов с Android. Но эти ответы устарели, и большинство методов в этих ответах устарели/устарели.
Я пытаюсь получить файл из локального хранилища с помощью Intent.ACTION_OPEN_DOCUMENT и загрузить его на сервер с помощью Retrofit. Но я не могу преобразовать экземпляр Uri в файл. Кроме того, я не могу загрузить этот файл с помощью Retrofit.
Вот код, который я использовал для получения файла:
class MainActivity : AppCompatActivity() {
private val DEVICE_PATH: Int = 398
private val BASE_URL = "https://pdftoworder.com/"
private lateinit var pdfClient: PDFClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val logging = HttpLoggingInterceptor()
logging.level = (HttpLoggingInterceptor.Level.BODY)
val okHttpClient = OkHttpClient
.Builder()
.addInterceptor(logging)
.build()
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create())
.build()
pdfClient = retrofit.create(PDFClient::class.java)
getPath.setOnClickListener { getFileUri() }
}
fun getFileUri(){
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
//intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
intent.type = "application/pdf"
startActivityForResult(intent, DEVICE_PATH)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == DEVICE_PATH && resultCode == Activity.RESULT_OK) {
data?.data?.let {uri ->
Log.d("PATHURL", "${uri.path} ${File(uri.path!!).name}")
lifecycleScope.launch {
//val api_key = RequestBody.create(MediaType.parse("text/plain"), "somevalue")
try {
val api_key = "DzkpCKjktggtCT1ZE8bFqca7anmmkpOcg975".toRequestBody("text/plain".toMediaTypeOrNull())
val tool_uid = "PR5".toRequestBody("text/plain".toMediaTypeOrNull())
val a = getRealPathFromURI(uri)
val file: File = File(uri.path!!)
val requestFile: RequestBody = file.asRequestBody("application/pdf".toMediaTypeOrNull())
val multipartBody: MultipartBody.Part = MultipartBody.Part.createFormData("input", file.name, requestFile)
val result = pdfClient.convert(
input = multipartBody,
api_key = api_key,
tool_uid = tool_uid
)
Log.d("PATHURL", "${uri.path}")
}catch (ex: Exception){
Log.d("PATHURL", "fatal ${ex.message}")
}
}
}
}
}
fun getPath(context: Context, uri: Uri): String? {
// DocumentProvider
if (DocumentsContract.isDocumentUri(context, uri)) {
System.out.println("getPath() uri: " + uri.toString())
System.out.println("getPath() uri authority: " + uri.getAuthority())
System.out.println("getPath() uri path: " + uri.getPath())
// ExternalStorageProvider
if ("com.android.externalstorage.documents" == uri.getAuthority()) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":").toTypedArray()
val type = split[0]
println("getPath() docId: " + docId + ", split: " + split.size + ", type: " + type)
// This is for checking Main Memory
return if ("primary".equals(type, ignoreCase = true)) {
if (split.size > 1) {
Environment.getExternalStorageDirectory().toString() + "/" + split[1] + "/"
} else {
Environment.getExternalStorageDirectory().toString() + "/"
}
// This is for checking SD Card
} else {
"storage" + "/" + docId.replace(":", "/")
}
}
}
return null
}
fun getRealPathFromURI(contentUri: Uri?): String? {
val proj = arrayOf(MediaStore.Images.Media.DATA)
val cursor = contentResolver.query(contentUri!!, proj, null, null, null) ?: return null
val column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor.moveToFirst()
return cursor.getString(column_index)
}
}
interface PDFClient {
@POST("api/convert")
@Multipart
suspend fun convert(
@Part input: MultipartBody.Part,
@Part("api_key") api_key: RequestBody,
@Part("tool_uid") tool_uid: RequestBody
): ResponseBody
}
Ошибка, которую я получаю:
document/raw:/storage/emulated/0/Download/Question_Bank/26_9_day_CSE_summer_final_2018_Wireless Programming.pdf (No such file or directory)
Here my goals are:
- Получить файл с андроида
- Загрузите этот файл на сервер, используя модификацию
- Скачать файл с сервера
- Сохраните этот файл в локальном хранилище
Любая небольшая помощь будет оценена. Я также создал GitHub Repo, чтобы воспроизвести проблему.
ACTION_GET_CONTENT
, иACTION_OPEN_DOCUMENT
дают вамUri
к некоторому контенту. Нет требования, чтобы этот контент был файлом в файловой системе, не говоря уже о том, что вы можете каким-то образом добраться до этого файла. ИспользуйтеInputStreamRequestBody
, как указано в дубликате, для загрузки содержимого, указанногоUri
, на ваш сервер. - person CommonsWare   schedule 19.02.2020@POST("api/convert") @Multipart suspend fun convert( @Part("input") input: InputStreamRequestBody, @Part("api_key") api_key: RequestBody, @Part("tool_uid") tool_uid: RequestBody ): ResponseBody
законно ли такое использование? - person zoha131   schedule 19.02.2020