0
votes

In a legacy program that i am updating, i am receiving at some point a file uploaded by a user, this file need to be analyzed within an external service.

I know how to send a file to a service using spray. In particular i know how to take a file from disk as the spray api is design as such

In my current particular situation, i only have an inputstream rather than a file. This is a file that is uploaded by the user to perform some analysis on it. That is, once i have the file, i would send it to an external service for analysis. However the spray API, especially http data only works with a file and not input stream, which is the datatype in which i have the data after the file is uploaded. I'm dealing with some legacy code.

I was wondering how to deal with the fact that my file is at the moment an inputstream. I red somewhere that a solution could me to write to a temp file on disk and do the upload with it. But accessing the disk all the time for the matter sounds long to me.

Is there any other way ?

Below you can find a typical code i would write for the matter. However in this case, the file is only available to me in the form of an inputstream.

Edit1

import context.dispatcher // execution context for futures below

      val file     = new File((getClass.getResource("/Health-Benefit-Plans.pdf")).toURI)

      val pipeline = addCredentials(BasicHttpCredentials("xxxxx", "xxxxxx")) ~> sendReceive

      val payload  = MultipartFormData(Seq(BodyPart(file, "file", MediaTypes.`application/pdf`)))

      val request  = Post("xxxx/categorization?projectId=xxxxx&language=en", payload)
      pipeline(request)

Edit2:

Here is the code of BodyPart

    object BodyPart {
  @deprecated("Use a BodyPart.apply overload instead", "1.0/1.1/1.2")
  def forFile(fieldName: String, file: FormFile): BodyPart =
    apply(file, fieldName)

  def apply(file: File, fieldName: String): BodyPart = apply(file, fieldName, ContentTypes.`application/octet-stream`)
  def apply(file: File, fieldName: String, contentType: ContentType): BodyPart =
    apply(HttpEntity(contentType, HttpData(file)), fieldName, Map.empty.updated("filename", file.getName))

  def apply(formFile: FormFile, fieldName: String): BodyPart =
    formFile.name match {
      case Some(name) ⇒ apply(formFile.entity, fieldName, Map.empty.updated("filename", name))
      case None       ⇒ apply(formFile.entity, fieldName)
    }

  def apply(entity: HttpEntity, fieldName: String): BodyPart = apply(entity, fieldName, Map.empty[String, String])
  def apply(entity: HttpEntity, fieldName: String, parameters: Map[String, String]): BodyPart =
    BodyPart(entity, Seq(`Content-Disposition`("form-data", parameters.updated("name", fieldName))))
}

As you can see there is nothing to deal with inputstream or something alike.

1

1 Answers

0
votes

You could write the inputstream to a byte array in memory, if you're confident this won't cause problems for your use case (e.g. >2GB files). But honestly you should be able to upload an inputstream (provided you know the length) - what problem are you having when you try to use Spray to upload?