如何使用KTOR客户端获取请求获取图像/PNG?

发布于 2025-01-23 20:30:50 字数 70 浏览 2 评论 0原文

我正在尝试从客户端收到我的服务器的get请求。我使用Image/PNG内容类型的服务器响应。如何从Kotlin代码中收到图像?

I am trying to do a get request from a client get call to my server. My server response with a image/png content type. How can I recieve the image from my kotlin code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

猫腻 2025-01-30 20:30:50

您不仅可以下载图像,还可以下载任何其他文件。

创建KTOR-CLIENT,就像您通常这样做。

val client = HttpClient(OkHttp) {
    install(ContentNegotiation) {
        json(Json { isLenient = true; ignoreUnknownKeys = true })
    }
}

对于使用此客户端下载文件,请阅读响应使用bodyaschannel()将响应读为bytereadChannel。使用copyasChannel()在磁盘上写入数据,传递目标bytewritechannel

GlobalScope.launch(Dispatchers.IO) {
    val url = Url("FILE_DOWNLOAD_LINK")
    val file = File(url.pathSegments.last())
    client.get(url).bodyAsChannel().copyAndClose(file.writeChannel())
    println("Finished downloading..")
}

You can download not only an image but also any other file.

Create ktor-client as you usually do.

val client = HttpClient(OkHttp) {
    install(ContentNegotiation) {
        json(Json { isLenient = true; ignoreUnknownKeys = true })
    }
}

For downloading a file using this client, read response using bodyAsChannel() which reads the response as ByteReadChannel. Use copyAsChannel() to write the data on the disk, passing destination's ByteWriteChannel.

GlobalScope.launch(Dispatchers.IO) {
    val url = Url("FILE_DOWNLOAD_LINK")
    val file = File(url.pathSegments.last())
    client.get(url).bodyAsChannel().copyAndClose(file.writeChannel())
    println("Finished downloading..")
}
总攻大人 2025-01-30 20:30:50

如果您不需要将图像保存在存储中,则可以使用ByTearray内存源来解码图像。

如果预期较大的图像,那么在解码之前将其降低会很好,请参见此处(Android) android:bitmapfactory.decodestream()在带有2MB Free Heap的400kb文件中退出

内存采样ktor_version ='2.0.0'

val client = HttpClient(Android) { install(Logging) { level = LogLevel.ALL } }

suspend fun getBitmap(uri: Uri): Bitmap? {
    return runCatching {
        val byteArray = withContext(Dispatchers.IO) {
            client.get(Url(uri.toString())).readBytes()
        }

        return withContext(Dispatchers.Default) {
            ByteArrayInputStream(byteArray).use {
                val option = BitmapFactory.Options()
                option.inPreferredConfig = Bitmap.Config.RGB_565 // To save memory, or use RGB_8888 if alpha channel is expected 
                BitmapFactory.decodeStream(it, null, option)
            }
        }
    }.getOrElse {
        Log.e("getBitmap", "Failed to get bitmap ${it.message ?: ""}" )
        null
    }
}

If you do not need to save image in storage, you can use byteArray memory source to decode image.

If larger images are expected it would be good to downscale them prior decoding, see here (Android) Android: BitmapFactory.decodeStream() out of memory with a 400KB file with 2MB free heap

Also note that Ktor api often changes from version to version, in this sample the ktor_version = '2.0.0' is used.

val client = HttpClient(Android) { install(Logging) { level = LogLevel.ALL } }

suspend fun getBitmap(uri: Uri): Bitmap? {
    return runCatching {
        val byteArray = withContext(Dispatchers.IO) {
            client.get(Url(uri.toString())).readBytes()
        }

        return withContext(Dispatchers.Default) {
            ByteArrayInputStream(byteArray).use {
                val option = BitmapFactory.Options()
                option.inPreferredConfig = Bitmap.Config.RGB_565 // To save memory, or use RGB_8888 if alpha channel is expected 
                BitmapFactory.decodeStream(it, null, option)
            }
        }
    }.getOrElse {
        Log.e("getBitmap", "Failed to get bitmap ${it.message ?: ""}" )
        null
    }
}
小镇女孩 2025-01-30 20:30:50

我也面临这个问题。我通过像这样的目录的直接路径解决了这一问题:

routing {
    static("upload") {
        static("products") {
            files("D:\\KMP Projects\\store-server\\upload\\products")
        }
    }
}

基本上,这是产品JSON响应的路径:

{
    "id": 2,
    "name": "Clothing",
    "description": "Fashionable apparel and accessories for men, women, and children.",
    "price": 499,
    "categoryId": 5,
    "categoryTitle": "Clothing",
    "imageUrl": "/upload/products/Screenshot_2024-03-20_132220.png",
    "created_at": "4/5/2024",
    "updated_at": "4/5/2024",
    "total_stack": 1100,
    "brand": "Official Brand",
    "weight": 14.0,
    "dimensions": "Not Available",
    "isAvailable": true,
    "discountPrice": 7,
    "promotionDescription": "This is a Demo Promotion Description.",
    "averageRating": 2.2
},

基本上,您需要直接通过项目目录。

I was also facing this issue. And I resolved this one by passing the direct path of the directory like this:

routing {
    static("upload") {
        static("products") {
            files("D:\\KMP Projects\\store-server\\upload\\products")
        }
    }
}

basically, here is the path of the product json response:

{
    "id": 2,
    "name": "Clothing",
    "description": "Fashionable apparel and accessories for men, women, and children.",
    "price": 499,
    "categoryId": 5,
    "categoryTitle": "Clothing",
    "imageUrl": "/upload/products/Screenshot_2024-03-20_132220.png",
    "created_at": "4/5/2024",
    "updated_at": "4/5/2024",
    "total_stack": 1100,
    "brand": "Official Brand",
    "weight": 14.0,
    "dimensions": "Not Available",
    "isAvailable": true,
    "discountPrice": 7,
    "promotionDescription": "This is a Demo Promotion Description.",
    "averageRating": 2.2
},

Basically, you need to pass the project directory directly.

心凉怎暖 2025-01-30 20:30:50

您将要从KTOR服务器提供 static Content https://ktor.io/docs/serving-static-content.html

您创建一个静态文件夹,然后将图像放入其中:

static("/") {
    staticRootFolder = File("files")
}

设置后,您可以在该文件夹中引用文件。如果您也需要子文件夹中的文件,则可以添加一个额外的文件(“。”) line:

static("/") {
    staticRootFolder = File("files")
    files(".")
}

You're going to want to serve static content from your Ktor server: https://ktor.io/docs/serving-static-content.html

You create a static folder, then put your images in there:

static("/") {
    staticRootFolder = File("files")
}

After that's set up, you can reference files in that folder. If you want files in subfolders as well, you can add an extra files(".") line:

static("/") {
    staticRootFolder = File("files")
    files(".")
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文