在播放框架 2.0 中将文件作为流上传

Posted

技术标签:

【中文标题】在播放框架 2.0 中将文件作为流上传【英文标题】:Uploading file as stream in play framework 2.0 【发布时间】:2012-08-17 12:21:12 【问题描述】:

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

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

我已经设法使用以下简单的控制器进行上传:

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() 方法。

在传统的 servlet 应用程序中,我会编写一个这样的 servlet:

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

我一直在到处寻找,但没有找到任何解决方案。我找到的最接近的例子是Why makes calling error or done in a BodyParser's Iteratee the request hang in Play Framework 2.0?,但我没有找到如何修改它以满足我的需要。

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

谢谢。

【问题讨论】:

【参考方案1】:

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

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 的调用。

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 的参数,但我无法这样做。因此,我添加了一段 javascript 来更新输入字段的名称(因此也是 partName),它可以解决问题。

【讨论】:

有没有用 Java 而不是 Scala 来做这件事? :(

以上是关于在播放框架 2.0 中将文件作为流上传的主要内容,如果未能解决你的问题,请参考以下文章

Python 3:如何在不保存在磁盘上的情况下将 pandas 数据帧作为 csv 流上传?

初识Apache Flink - 数据流上的有状态计算

html 读取本地文件后使用文件二进制流上传文件

播放框架文件上传空参数

从 json 文件流上传批量数据时,最后一批永远不会上传到 Solr

为啥 .NET 框架项目可以作为参考添加到 .NET Standard 2.0 项目中?