在play framework 2.0中将文件上传为流 [英] Uploading file as stream in play framework 2.0

查看:171
本文介绍了在play framework 2.0中将文件上传为流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个允许用户上传文件的play 2.0 java应用程序。这些文件存储在我使用Java库访问的第三方服务上,我在此API中使用的方法具有以下签名:

I'm writing a play 2.0 java application that allows users to upload files. Those files are stored on a third-party service I access using a Java library, the method I use in this API has the following signature:

void store(InputStream stream, String path, String contentType)

我已成功制作使用以下简单控制器上传工作:

I've managed to make uploads working using the following simple controller:

public static Result uploadFile(String path) {
    MultipartFormData body = request().body().asMultipartFormData();
    FilePart filePart = body.getFile("files[]");
    InputStream is    = new FileInputStream(filePart.getFile())
    myApi.store(is,path,filePart.getContentType()); 
    return ok();
  }

我担心这个解决方案效率不高,因为默认情况下播放框架存储客户端在服务器上的临时文件中上传的所有数据然后在控制器中调用我的uploadFile()方法。

My concern is that this solution is not efficient because by default the play framework stores all the data uploaded by the client in a temporary file on the server then calls my uploadFile() method in the controller.

在传统的servlet应用程序中,我会用这种方式写一个servlet:

In a traditional servlet application I would have written a servlet behaving this way:

myApi.store(request.getInputStream(), ...)

我去过到处搜寻,没有找到任何解决方案。我找到的最接近的例子是为什么调用错误或在BodyParser的Iteratee中完成请求在Play Framework 2.0中挂起?但我没有找到如何根据我的需要修改它。

I have been searching everywhere and didn't find any solution. The closest example I found is Why makes calling error or done in a BodyParser's Iteratee the request hang in Play Framework 2.0? but I didn't found how to modify it to fit my needs.

在play2中是否有办法实现这种行为,即客户端上传的数据是否直接通过网络应用程序到达另一个系统?

Is there a way in play2 to achieve this behavior, i.e. having the data uploaded by the client to go "through" the web-application directly to another system ?

谢谢。

推荐答案

我已经能够使用以下Scala控制器将数据流式传输到我的第三方API代码:

I've been able to stream data to my third-party API using the following Scala controller code:

def uploadFile() = 
    Action( parse.multipartFormData(myPartHandler) ) 
    {
      request => Ok("Done")
    }

def myPartHandler: BodyParsers.parse.Multipart.PartHandler[MultipartFormData.FilePart[Result]] = {
        parse.Multipart.handleFilePart {
          case parse.Multipart.FileInfo(partName, filename, contentType) =>
            //Still dirty: the path of the file is in the partName...
            String path = partName;

            //Set up the PipedOutputStream here, give the input stream to a worker thread
            val pos:PipedOutputStream = new PipedOutputStream();
            val pis:PipedInputStream  = new PipedInputStream(pos);
            val worker:UploadFileWorker = new UploadFileWorker(path,pis);
            worker.contentType = contentType.get;
            worker.start();

            //Read content to the POS
            Iteratee.fold[Array[Byte], PipedOutputStream](pos) { (os, data) =>
              os.write(data)
              os
            }.mapDone { os =>
              os.close()
              Ok("upload done")
            }
        }
   }

UploadFileWorker是一个非常简单的Java类,它包含对第三方API的调用。

The UploadFileWorker is a really simple Java class that contains the call to the thrid-party API.

public class UploadFileWorker extends Thread {
String path;
PipedInputStream pis;

public String contentType = "";

public UploadFileWorker(String path, PipedInputStream pis) {
    super();
    this.path = path;
    this.pis = pis;
}

public void run() {
    try {
        myApi.store(pis, path, contentType);
        pis.close();
    } catch (Exception ex) {
        ex.printStackTrace();
        try {pis.close();} catch (Exception ex2) {}
    }
}

}

这不是完全完美的,因为我宁愿将路径恢复为Action的参数,但我还没有能够这样做。因此,我添加了一段更新输入字段名称(以及partName)的javascript,并且它可以解决问题。

It's not completely perfect because I would have preferred to recover the path as a parameter to the Action but I haven't been able to do so. I thus have added a piece of javascript that updates the name of the input field (and thus the partName) and it does the trick.

这篇关于在play framework 2.0中将文件上传为流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆