Vert.x 使用 BLOB 和 hibernate 将数据库中的数据分块回答
Vert.x chunked answer with data from database using BLOB and hibernate
我尝试使用 Hibernate 5.2 11.Final(BLOB 类型)和 Vert.x 3.4.2 从数据库 (Postgresql 9.6.5) 发送二进制数据作为响应,但我收到错误消息响应(它看起来像我丢失了一些位)。这是我在 Kotlin 中的代码:
fun getFile(user: User, messageId: Long, fileId: Short, response: HttpServerResponse) {
val mediaContent = mediaContentRepository.getFile(messageId, fileId)
when {
mediaContent == null ->
response.apply { statusCode = 404 }.end()
conversationUserRepository.authorize(user.id!!, mediaContent.message!!.conversation!!.id, mediaContent.message!!.created) ->
response.setChunked(true)
.putHeader("Content-Disposition", "attachment; filename=\"${mediaContent.name}\"") //TODO: prevent injections
.putHeader("Content-Type", mediaContent.contentType)
//.putHeader("Content-Length", mediaContent.file.length().toString())
.apply {
//write(Buffer.buffer().apply { delegate.setBytes(0, mediaContent.file.binaryStream.readAllBytes()) })
val buffer = Buffer.buffer(BUFFER_SIZE)
val stream = mediaContent.file.binaryStream
val byteArray = ByteArray(BUFFER_SIZE)
for (i in (0L..(mediaContent.file.length() / BUFFER_SIZE))) {
val bytesRead = stream.read(byteArray)
buffer.delegate.setBytes(0, byteArray, 0, bytesRead)
write(if (bytesRead == BUFFER_SIZE) buffer else buffer.slice(0, bytesRead))
}
}
.end()
else ->
response.apply { statusCode = 403 }.end()
}
}
但是当我尝试使用此行一次发送整个文件时,响应是正确的。
write(Buffer.buffer().apply { delegate.setBytes(0, mediaContent.file.binaryStream.readAllBytes()) })
知道我做错了什么吗?
编辑:我通常会收到针对同一文件的不同响应,这也很有帮助。
我让它工作了,但我不知道它为什么工作。就我而言,在循环中重用 vert.x 缓冲区似乎存在问题。下面的代码
fun getFile(user: User, messageId: Long, fileId: Short, response: HttpServerResponse) {
val mediaContent = mediaContentRepository.getFile(messageId, fileId)
when {
mediaContent == null ->
response.apply { statusCode = 404 }.end()
conversationUserRepository.authorize(user.id!!, mediaContent.message!!.conversation!!.id, mediaContent.message!!.created) ->
response.putHeader("Content-Disposition", "attachment; filename=\"${mediaContent.name}\"") //TODO: prevent injections
.putHeader("Content-Type", mediaContent.contentType)
.putHeader("Content-Length", mediaContent.file.length().toString())
.apply {
val stream = mediaContent.file.binaryStream
val byteArray = ByteArray(BUFFER_SIZE)
for (i in (0L..(mediaContent.file.length() / BUFFER_SIZE))) {
val bytesRead = stream.read(byteArray)
write(Buffer(io.vertx.core.buffer.Buffer.buffer(byteArray)
.let {
if (bytesRead == BUFFER_SIZE) it
else it.slice(0, bytesRead)
}))
}
}
.end()
else ->
response.apply { statusCode = 403 }.end()
}
}
我尝试使用 Hibernate 5.2 11.Final(BLOB 类型)和 Vert.x 3.4.2 从数据库 (Postgresql 9.6.5) 发送二进制数据作为响应,但我收到错误消息响应(它看起来像我丢失了一些位)。这是我在 Kotlin 中的代码:
fun getFile(user: User, messageId: Long, fileId: Short, response: HttpServerResponse) {
val mediaContent = mediaContentRepository.getFile(messageId, fileId)
when {
mediaContent == null ->
response.apply { statusCode = 404 }.end()
conversationUserRepository.authorize(user.id!!, mediaContent.message!!.conversation!!.id, mediaContent.message!!.created) ->
response.setChunked(true)
.putHeader("Content-Disposition", "attachment; filename=\"${mediaContent.name}\"") //TODO: prevent injections
.putHeader("Content-Type", mediaContent.contentType)
//.putHeader("Content-Length", mediaContent.file.length().toString())
.apply {
//write(Buffer.buffer().apply { delegate.setBytes(0, mediaContent.file.binaryStream.readAllBytes()) })
val buffer = Buffer.buffer(BUFFER_SIZE)
val stream = mediaContent.file.binaryStream
val byteArray = ByteArray(BUFFER_SIZE)
for (i in (0L..(mediaContent.file.length() / BUFFER_SIZE))) {
val bytesRead = stream.read(byteArray)
buffer.delegate.setBytes(0, byteArray, 0, bytesRead)
write(if (bytesRead == BUFFER_SIZE) buffer else buffer.slice(0, bytesRead))
}
}
.end()
else ->
response.apply { statusCode = 403 }.end()
}
}
但是当我尝试使用此行一次发送整个文件时,响应是正确的。
write(Buffer.buffer().apply { delegate.setBytes(0, mediaContent.file.binaryStream.readAllBytes()) })
知道我做错了什么吗?
编辑:我通常会收到针对同一文件的不同响应,这也很有帮助。
我让它工作了,但我不知道它为什么工作。就我而言,在循环中重用 vert.x 缓冲区似乎存在问题。下面的代码
fun getFile(user: User, messageId: Long, fileId: Short, response: HttpServerResponse) {
val mediaContent = mediaContentRepository.getFile(messageId, fileId)
when {
mediaContent == null ->
response.apply { statusCode = 404 }.end()
conversationUserRepository.authorize(user.id!!, mediaContent.message!!.conversation!!.id, mediaContent.message!!.created) ->
response.putHeader("Content-Disposition", "attachment; filename=\"${mediaContent.name}\"") //TODO: prevent injections
.putHeader("Content-Type", mediaContent.contentType)
.putHeader("Content-Length", mediaContent.file.length().toString())
.apply {
val stream = mediaContent.file.binaryStream
val byteArray = ByteArray(BUFFER_SIZE)
for (i in (0L..(mediaContent.file.length() / BUFFER_SIZE))) {
val bytesRead = stream.read(byteArray)
write(Buffer(io.vertx.core.buffer.Buffer.buffer(byteArray)
.let {
if (bytesRead == BUFFER_SIZE) it
else it.slice(0, bytesRead)
}))
}
}
.end()
else ->
response.apply { statusCode = 403 }.end()
}
}