PlayFramework. How to upload a photo using an external endpoint?

388 Views Asked by At

How do I upload a photo using a URL in the playframework? I was thinking like this:

URL url = new URL("http://www.google.ru/intl/en_com/images/logo_plain.png");
BufferedImage img = ImageIO.read(url);
File newFile = new File("google.png");
ImageIO.write(img, "png", newFile);

But maybe there's another way. In the end I have to get the File and file name.

Example controller:

public static Result uploadPhoto(String urlPhoto){ 
    Url url = new Url(urlPhoto); //doSomething 
    //get a picture and write to a temporary file
    File tempPhoto = myUploadPhoto;
    uploadFile(tempPhoto); // Here we make a copy of the file and save it to the file system.
    return ok('something');
}
2

There are 2 best solutions below

6
anquegi On

To get that photo you can use The play WS API, the code behind is an example extracted from the play docs in the section Processing large responses, I recommend you to read the full docs here

final Promise<File> filePromise = WS.url(url).get().map(
        new Function<WSResponse, File>() {
            public File apply(WSResponse response) throws Throwable {

                InputStream inputStream = null;
                OutputStream outputStream = null;
                try {
                    inputStream = response.getBodyAsStream();

                    // write the inputStream to a File
                    final File file = new File("/tmp/response.txt");
                    outputStream = new FileOutputStream(file);

                    int read = 0;
                    byte[] buffer = new byte[1024];

                    while ((read = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, read);
                    }

                    return file;
                } catch (IOException e) {
                    throw e;
                } finally {
                    if (inputStream != null) {inputStream.close();}
                    if (outputStream != null) {outputStream.close();}
                }

            }
        }
);

Where url is :

String url = "http://www.google.ru/intl/en_com/images/logo_plain.png"

This is as suggested in play documentation for large files:

*

When you are downloading a large file or document, WS allows you to get the response body as an InputStream so you can process the data without loading the entire content into memory at once.

*

0
sebster On

Pretty much the same as the above answer then some...

Route: POST /testFile 'location of your controller goes here'

Request body content: {"url":"http://www.google.ru/intl/en_com/images/logo_plain.png"}

Controller(using code from JavaWS Processing large responses):

public static Promise<Result> saveFile() {
    //you send the url in the request body in order to avoid complications with encoding
    final JsonNode body = request().body().asJson();
    // use new URL() to validate... not including it for brevity
    final String url = body.get("url").asText();
    //this one's copy/paste from Play Framework's docs 
    final Promise<File> filePromise = WS.url(url).get().map(response -> {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = response.getBodyAsStream();
            final File file = new File("/temp/image");
            outputStream = new FileOutputStream(file);
            int read = 0;
            byte[] buffer = new byte[1024];
            while ((read = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, read);
            }
            return file;
        } catch (IOException e) {
            throw e;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }); // copy/paste ended
    return filePromise.map(file -> (Result) ok(file.getName() + " saved!")).recover(
            t -> (Result) internalServerError("error -> " + t.getMessage()));
}

And that's it...

In order to serve the file after the upload phase you can use this answer(I swear I'm not promoting myself...): static asset serving from absolute path in play framework 2.3.x