从 uri 获取 FileInputStream 以上传图片

Posted

技术标签:

【中文标题】从 uri 获取 FileInputStream 以上传图片【英文标题】:Get FileInputStream from uri to upload image 【发布时间】:2022-01-16 19:40:55 【问题描述】:

我在没有 WRITE_EXTERNAL_PERMISIONREAD_EXTERNAL_PERMISION

的情况下成功地从图库或相机中获取图像

现在我想将该图像上传到 FTP 服务器

ImageSetter.kt

class ImageSetter(
    private val activity: FragmentActivity,
    private val imageView: ImageView,
    val uriCallback:(uri:Uri?) -> Unit,
) : DefaultLifecycleObserver 

    private lateinit var getContent: ActivityResultLauncher<String>
    private lateinit var dispatchTakePicture: ActivityResultLauncher<Uri>

    private val registry = activity.activityResultRegistry
    private var uri: Uri? = null

    override fun onCreate(owner: LifecycleOwner) 
        getContent =
            registry.register(
                "select-key",
                owner,
                ActivityResultContracts.GetContent()
            )
                it?.let
                    uriCallback.invoke(it)
                    this.uri = it
                    imageView.setImageURI(uri)
                
            

        dispatchTakePicture =
            registry.register(
                "take-keys",
                owner,
                ActivityResultContracts.TakePicture()
            )
                if (it) 
                    Log.d("takePicture", "Success")
                    imageView.setImageURI(uri)
                 else 
                    Log.d("takePicture", "Failed")
                
            
    

    fun selectImage()
        val items = arrayOf("Select an image", "Take Photo")

        AlertDialog.Builder(activity)
            .setItems(items)  dialog, which ->
                Log.d("dialog", dialog.toString())
                Log.d("which", which.toString())
                when(which)
                    0 -> getContent.launch("image/*")
                    1 -> takePicture()
                
            
            .show()
    

    private fun takePicture()
        val filename = UUID.randomUUID().toString() + ".jpg"
        val path = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        val file = File(path, filename)

        uri = FileProvider.getUriForFile(activity,
            BuildConfig.APPLICATION_ID + ".provider", file);
        uriCallback(uri)
        dispatchTakePicture.launch(uri)
        Log.d("Uri", uri.toString())
    

为了将 图像文件上传到服务器,我需要 InputStream 但我无法获取 原始图像文件 将其发布到服务器.

我是否需要任何许可才能这样做?

MainActivity.kt

class MainActivity : AppCompatActivity() 
    private lateinit var observer: ImageSetter
    private lateinit var photoIv:ImageView
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        photoIv = findViewById(R.id.photoIv)
        observer = ImageSetter(this, photoIv) photoUri->
        
        var openInputStream = contentResolver?.openInputStream(photoUri!!)
        var format = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
           var file = File(filesDir, "$format.jpg")
           var fileoutputStream = FileOutputStream(file)
           openInputStream?.copyTo(fileoutputStream)
           openInputStream?.close()
           fileoutputStream.close()
           fileAbsolutPath = file.absolutePath
  
        
        lifecycle.addObserver(observer)
        observer.selectImage()
    

编辑

我有一个工作班可以将 fileInputStream 上传到具有方法的 FTP 服务器

public static boolean uploadImageFileOnFtpServer(FileInputStream inputStream, String clientFileName)
...

现在我只想弄清楚如何从 Uri 获取 fileInputStream。

【问题讨论】:

我认为 InputStream 可以。请确认。 进一步:如果您使用相机拍摄图像,您可以使用文件提供程序作为文件路径。所以在这种情况下,你有一个路径并且可以使用 FileInputStream。 我有 uri,如何将我的 uri 转换为 fileInputStrem。请参阅编辑@blackapps 你对我说的话没有反应。 val file = File(path, filename) 您有一个 File 实例,因此您可以将它用于新的 FileInputStream。此外,如果您只有一个 uri,您也可以将 InputStream 传递给您的上传函数。 have a working class to upload fileInputStream to FTP Server which has a method 将其更改为采用 InputStream。或者为 InputStream 添加一个重载成员。但正如你现在拥有的那样,你也可以传递一个 InputStream 。我已经说过了。 【参考方案1】:

您需要传递 URI 来获取文件并将此文件输入流并上传到服务器。

  var file=getFileFromUri(uri!!)
  val inputStream: InputStream = FileInputStream(file)

并从以下方法获取文件。

 fun getFileFromUri(uri: Uri): File? 
        if (uri.path == null) 
            return null
        
        var realPath = String()
        val databaseUri: Uri
        val selection: String?
        val selectionArgs: Array<String>?
        if (uri.path!!.contains("/document/image:")) 
            databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
            selection = "_id=?"
            selectionArgs = arrayOf(DocumentsContract.getDocumentId(uri).split(":")[1])
         else 
            databaseUri = uri
            selection = null
            selectionArgs = null
        
        try 
            val column = "_data"
            val projection = arrayOf(column)
            val cursor = contentResolver.query(
                databaseUri,
                projection,
                selection,
                selectionArgs,
                null
            )
            cursor?.let 
                if (it.moveToFirst()) 
                    val columnIndex = cursor.getColumnIndexOrThrow(column)
                    realPath = cursor.getString(columnIndex)
                
                cursor.close()
            
         catch (e: Exception) 
            Log.i("GetFileUri Exception:", e.message ?: "")
        
        val path = if (realPath.isNotEmpty()) realPath else 
            when 
                uri.path!!.contains("/document/raw:") -> uri.path!!.replace(
                    "/document/raw:",
                    ""
                )
                uri.path!!.contains("/document/primary:") -> uri.path!!.replace(
                    "/document/primary:",
                    "/storage/emulated/0/"
                )
                else -> return null
            
        
        return File(path)
    

【讨论】:

以上是关于从 uri 获取 FileInputStream 以上传图片的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 OutOfMemory 错误的情况下从 FileInputStream 获取字节数组

如何从 Uri 获取位图?

有没有一种直接的方法可以从文件 Uri 中获取父目录的 Uri?

从查找 URI 获取电话号码

Android - 如何从原始文件中获取 Uri?

如何从 Uri xamarin android 获取实际路径