Skip to content

StreamedFile is not consumed #12056

@abishai

Description

@abishai

Expected Behavior

Usercase: receiving big entries from database I try to compress them and return as a StreamedFile with minimal memory usage.


@Controller
class Controller {

    @Get("/download", produces = [MediaType.APPLICATION_OCTET_STREAM])
    suspend fun download(): StreamedFile = coroutineScope {
        provide()
    }

    suspend fun provide(): StreamedFile = coroutineScope {
        val inputStream = PipedInputStream(1024 * 10)
        val outputStream = PipedOutputStream(inputStream)

        launch(Dispatchers.Default) {
            outputStream.use { stream ->
                ZipOutputStream(stream).use { stream ->
                    (0 until 1000).forEach { i ->
                        println("Processing entry $i")
                        stream.putNextEntry(ZipEntry("$i.txt"))
                        ByteArrayInputStream(getRandomString(1024).toByteArray()).use { it.copyTo(stream) }
                        stream.closeEntry()
                        println("Processing entry $i complete")
                    }
                }
            }

            println("Coroutine complete.")
        }

        println("Returning streaming file stub")
        StreamedFile(inputStream, MediaType.APPLICATION_OCTET_STREAM_TYPE)
            .attach("export.zip")
    }

    private fun getRandomString(length: Int): String {
        val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9') + ' '
        return String(CharArray(length) { allowedChars.random() })
    }
}

Actual Behaviour

Stream is not read, leading to PipedInputStream overflow, hanging the entire process.

Steps To Reproduce

Start the attached project and try to download file from /download If generated content doesn't fit PipedInputStream, the process hangs.

  • Returning streaming file stub is visible, meaning that stream is passed and data pump has started in another thread
  • Several Processing entry $i complete is visible. Corresponds to buffer size and entries size
  • Coroutine complete. is not visible

Environment Information

FreeBSD 14.3
OpenJDK21

Example Application

hanging-pipe.zip

Version

4.9.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions