2016-08-05 48 views
0

Ich versuche, eine Datei mit Play-API-Framework herunterladen. Da die gesamte Datenzugriffsschicht bereits mit Futures implementiert wurde, möchte ich auch den Download mit asynchronen Aktionen erhalten. Der folgende Codeabschnitt funktioniert jedoch nicht. Und wenn ich nicht arbeite, meine ich, dass die an den Client gesendete Datei nicht mit der Datei auf dem Server übereinstimmt.laden Sie eine Datei mit Play-Web-API (async)

val sourcePath = "/tmp/sample.pdf" 

    def downloadAsync = Action.async { 
    Future.successful(Ok.sendFile(new java.io.File(sourcePath))) 
    } 

Doch dieses Stück funktioniert:

def download = Action { 
    Ok.sendFile(new java.io.File(sourcePath)) 
    } 

Jeder Vorschlag, wie ich die Asynchron-Methode zu arbeiten zu bekommen?

+1

Sowohl "Action.apply" als auch "Action.async" sind async! Im ersten Fall übergeben Sie einen "normalen" Wert (kein Future) und in einem anderen Fall übergeben Sie ein Future, siehe [hier] (https://www.playframework.com/documentation/2.4.x/ScalaAsync#actions-are -asynchron-standardmäßig). Da Play selbst den [zweiten Weg] (https://www.playframework.com/documentation/2.4.x/ScalaStream#serving-files) empfiehlt (und es wird async), das ist der Weg zu gehen .. :) –

Antwort

2

Sie müssen Action.async hier nicht verwenden, da Ok.sendFile bereits nicht blockiert ist. Von the docs:

Abspielaktionen sind standardmäßig asynchron. Zum Beispiel ist der { Ok(...) } Teil des Codes im nachfolgenden Controller-Code nicht der Methodenkörper des Controllers. Es handelt sich um eine anonyme Funktion, die an die apply-Methode des Objekts Action übergeben wird, die ein Objekt vom Typ Aktion erstellt. Intern wird die anonyme Funktion, die Sie geschrieben haben, aufgerufen und ihr Ergebnis wird in eine Future eingeschlossen.

def echo = Action { request => 
    Ok("Got request [" + request + "]") 
} 

Hinweis: Sowohl Action.apply und Action.async Action-Objekte erstellen, die intern auf die gleiche Art und Weise behandelt werden. Es gibt eine einzige Art von Aktion, die asynchron ist und nicht zwei Arten (eine synchrone und eine asynchrone). Der Builder .async dient lediglich dazu, das Erstellen von Aktionen basierend auf APIs zu vereinfachen, die ein Future zurückgeben, wodurch das Schreiben von nicht blockierendem Code erleichtert wird.

Mit anderen Worten, in diesem speziellen Fall, keine Sorge über Ihre Result in eine Future Verpackung und Ok.sendFile gerade zurück.


Schließlich funktionieren beide Versionen wie erwartet (die Datei wurde ordnungsgemäß geliefert). Vielleicht haben Sie ein anderes Problem, das nicht damit zusammenhängt, wie Sie Ihre Handlungen erklärt haben.

+0

danke für den Kommentar. Ich habe es mit einer PDF-Datei versucht und es funktioniert nicht. Es funktioniert mit Beispieltextdatei. –

+0

Und für den genauen Grund, den Sie erwähnten, bevorzuge ich Async-Version, da die Datenzugriffsschichtmethoden alle zukünftigen Ergebnisse zurückgeben. –

+0

Ich habe es jetzt mit einem Bild und auch einem PDF probiert. Alles funktioniert wie ein Zauber. Vielleicht können Sie weitere Informationen hinzufügen. – marcospereira