使用 RandomAccessFile 读取完成的指令
Directive to complete with RandomAccessFile read
我有一个很大的数据文件并用该文件的很小一部分响应 GET 请求,如 Array[Byte]
指令是:
get {
dataRepo.load(param).map(data =>
complete(
HttpResponse(
entity = HttpEntity(myContentType, data),
headers = List(gzipContentEncoding)
)
)
).getOrElse(complete(HttpResponse(status = StatusCodes.NoContent)))
}
其中 dataRepo.load
是以下函数:
val pointers: Option[Long, Int] = calculateFilePointers(param)
pointers.map { case (index, length) =>
val dataReader = new RandomAccessFile(dataFile, "r")
dataReader.seek(index)
val data = Array.ofDim[Byte](length)
dataReader.readFully(data)
data
}
是否有更有效的方法将 RandomAccessFile 读取直接返回到响应中,而不是必须先完全读取它?
您可以创建一个 Iterator[Array[Byte]]
来一次读取文件块,而不是将数据读入 Array[Byte]
:
val dataReader = new RandomAccessFile(dataFile, 'r')
val chunkSize = 1024
Iterator
.range(index, index + length, chunkSize)
.map { currentIndex =>
val currentBytes =
Array.ofDim[Byte](Math.min(chunkSize, length - currentIndex))
dataReader seek currentIndex
dataReader readFully currentBytes
currentBytes
}
这个迭代器现在可以提供一个 akka Source
:
val source : Source[Array[Byte], _] =
Source fromIterator (() => dataRepo.load(param))
然后可以提供一个 HttpEntity:
val byteStrSource : Source[ByteString, _] = source.map(ByteString.apply)
val httpEntity = HttpEntity(myContentType, byteStrSource)
现在每个客户端一次只会使用 1024 字节的内存,而不是读取文件的全长。这将使您的服务器更有效地处理多个并发请求,并允许您的 dataRepo.load
立即使用惰性 Source
值 return 而不是使用 Future
。
我有一个很大的数据文件并用该文件的很小一部分响应 GET 请求,如 Array[Byte]
指令是:
get {
dataRepo.load(param).map(data =>
complete(
HttpResponse(
entity = HttpEntity(myContentType, data),
headers = List(gzipContentEncoding)
)
)
).getOrElse(complete(HttpResponse(status = StatusCodes.NoContent)))
}
其中 dataRepo.load
是以下函数:
val pointers: Option[Long, Int] = calculateFilePointers(param)
pointers.map { case (index, length) =>
val dataReader = new RandomAccessFile(dataFile, "r")
dataReader.seek(index)
val data = Array.ofDim[Byte](length)
dataReader.readFully(data)
data
}
是否有更有效的方法将 RandomAccessFile 读取直接返回到响应中,而不是必须先完全读取它?
您可以创建一个 Iterator[Array[Byte]]
来一次读取文件块,而不是将数据读入 Array[Byte]
:
val dataReader = new RandomAccessFile(dataFile, 'r')
val chunkSize = 1024
Iterator
.range(index, index + length, chunkSize)
.map { currentIndex =>
val currentBytes =
Array.ofDim[Byte](Math.min(chunkSize, length - currentIndex))
dataReader seek currentIndex
dataReader readFully currentBytes
currentBytes
}
这个迭代器现在可以提供一个 akka Source
:
val source : Source[Array[Byte], _] =
Source fromIterator (() => dataRepo.load(param))
然后可以提供一个 HttpEntity:
val byteStrSource : Source[ByteString, _] = source.map(ByteString.apply)
val httpEntity = HttpEntity(myContentType, byteStrSource)
现在每个客户端一次只会使用 1024 字节的内存,而不是读取文件的全长。这将使您的服务器更有效地处理多个并发请求,并允许您的 dataRepo.load
立即使用惰性 Source
值 return 而不是使用 Future
。