如何发送csv文件作为akka http响应?

时间:2019-06-07 06:25:44

标签: scala akka akka-stream akka-http

我需要从数据库中获取数据并创建数据的CSV文件并返回它,并且应该下载该文件。并在发送响应后将其从服务器中删除。我用了这个Simple CSV streaming example

代码段:

def getAllRetailersCsvData: Route =
post {
  entity(As[String]) { body =>

  //removed database calls and added data from db 
  val retailersInformation = RetailersInformation(
                              List(
                              RetailerInformation(Target,277,8360.56,267.12),
                              RetailerInformation(Amazon,85,1370.0,540.11),
                              RetailerInformation(Walmart,77,1431.32,344.38),
                              RetailerInformation(Best buy,63,1213.22,160.84),
                              RetailerInformation(Others,22,391.77,108.1),
                              RetailerInformation(Others,17,317.86,157.93),
                              RetailerInformation(Ebay,4,46.97,14.55),
                              RetailerInformation(Big lots,3,24.0,12.33),
                              RetailerInformation(Smith's,2,44.98,218.43),
                              RetailerInformation(Kroger,2,39.98,29.09)),23)


  implicit val retailerAsCsv = Marshaller.strict[RetailersInformation, ByteString] { t =>
  Marshalling.WithFixedContentType(ContentTypes.`text/csv(UTF-8)`, () => {
  ByteString(t.retailersInformation.map(r => csvData(r)).mkString("\n"))
})
}

  implicit val csvStreaming: CsvEntityStreamingSupport = EntityStreamingSupport.csv()

  val eventualRetailersInfo = Future(retailersInformation)
  onComplete(eventualRetailersInfo) {

  case Success(info: RetailersInformation) =>
  complete(Source.single(info))
  case Failure(exception) =>
  logger.error(s"Got an exception when getting all retailers info by $campaignId , exception $exception")
  complete(HttpResponse(InternalServerError, entity = generate(ErrorResponse(ErrorMessage))))
}
}
}

问题是,当我从邮递员那里打了那条路线时,我得到了正确的内容,但没有csv文件。

输出:

Retailer Name,Receipts Submitted,Brand Total,Basket Size
"Target","277","267.12","8360.56"
"Amazon","85","540.11","1370.0"
"Walmart","77","344.38","1431.32"
"Best buy","63","160.84","1213.22"
"Others","22","108.1","391.77"
"Others","17","157.93","317.86"
"Ebay","4","14.55","46.97"
"Big lots","3","12.33","24.0"
"Smith's","2","218.43","44.98"
"Kroger","2","29.09","39.98"

与流式csv示例相比,我有一些不同之处。我有一个职位要求。不知道在哪里设置仅接受csv文本的标头。如果我接受,请作为我的Akka流概念初学者指导我。任何帮助将不胜感激。

谢谢

2 个答案:

答案 0 :(得分:0)

我猜您从Akka http处获取的是原始数据,可以将其转换为适当的响应 使用curl --output example.csv **application url**

答案 1 :(得分:0)

要解决此问题,首先我创建一个文件作为HTTP响应传递。

def writeToFile(content: String, campaignId: String): File = {
    val tempFolder = System.getProperty(TempDir)
    val file = new File(s"$tempFolder/retailers_$campaignId.csv")
    val bw = new BufferedWriter(new FileWriter(file))
    bw.write(content)
    bw.close()
    file
  }

def retailersInfoForCsvResponseHandler(response: Either[Throwable, Option[String]], campaignId: String): HttpResponse =
    response.fold({ err =>
      logger.error(s"An exception has occurred while getting retailersInfo for csv from snap3 service ${err.getMessage}")
      HttpResponse(StatusCodes.InternalServerError, entity = err.getMessage)
    }, response => {
      val file = writeToFile(response.fold("")(identity), campaignId)
      val source = FileIO.fromPath(file.toPath)
        .watchTermination() { case (_, result) =>
          result.onComplete(_ => file.delete())
        }

      HttpResponse(status = StatusCodes.OK, entity = HttpEntity(ContentTypes.`text/csv(UTF-8)`, source))
    })

对我有用。发送为响应的文件以及发送响应后的文件将被删除。