SomeStranger314
SomeStranger314

Reputation: 387

scala.xml node to virtual file to prepare downloading it

I am using scala and play framework to create an API server. On one of my API calls, I upload a JSON and after some meddling on the server, I send back an XML. This XML should then be downloaded as a text file and I figured it was easiest if I directly start a download in the backend and don't just create the file in the front-end.

I have successfully created the XML I wanted using the scala.xml package and I do have now a node object, that when printed looks strikingly like the XML I am looking for.

Scala's scala.xml.XML object has a method, aptly called save that allows me to make a file out of the XML. I could use that to create my XML, but that means that I have to save it on the hard drive, which is its own can of worms. But I am kind of dead in the water in how to save the file in RAM. Can anyone help me out here?

EDIT 1:

To clarify, on the front-end side I am calling this API with axios. At my user's computer, there should be a downloading dialogue opening, asking my user where to save the file which might be called foo.xml. As I understand it, I need to transform my XML into a file stream. I can do this easily by just saving it on the hard drive and use java.nio on it, but I was hoping there was a way to avoid the write on the hard drive just to read it back into a file stream and then delete it routine.

Upvotes: 0

Views: 94

Answers (2)

SomeStranger314
SomeStranger314

Reputation: 387

So, for everyone with a similar issue. It seems to be a much easier to change the data in the frontend and force the download.

I returned the data just as Matthias A. Eckhart suggested. And in the frontend I fed the data in this little function:

function download(filename, text) {
    const element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    element.setAttribute('download', filename);

    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();

    document.body.removeChild(element);

This solution was found here: https://stackoverflow.com/a/18197341/9094259

Credits to Matěj Pokorný

Upvotes: 0

Matthias A. Eckhart
Matthias A. Eckhart

Reputation: 5156

As far as I understood, you want to serve your clients an XML, i.e., sending an HTTP response with Content-Type: application/xml.

If this is what you want to do, then just pass your scala.xml.NodeSeq as an argument to your Ok call in the respective Action. As stated in the documentation, the Play Framework will automatically set the correct Content-Type in the response. There's no need to save the XML to a file beforehand, as you can directly send the XML as a response.

For example:

class MyController extends Controller {

  def processXml = Action { implicit request =>
    // Process XML
    val myXml: NodeSeq = getXml()
    Ok(myXml)
  }
}

Upvotes: 1

Related Questions