将文件从Angular ng-file-upload上传到Play for Scala

问题描述 投票:0回答:1

我正在尝试使用浏览器中的ng-file-upload上传一个.csv文件,并在后端使用Play for Scala2.5.x。

如果我在Play中使用moveTo ,则该文件已上传,但使用标头和尾标而不是普通文件生成:

request.body.moveTo(new File("c:\\tmp\\uploaded\\filetest.csv"))

有没有办法只保存数据部分?

另外,我尝试了以下

 def doUpload  = Action(parse.multipartFormData)  { request =>


    println(request.contentType.get)
    println(request.body)

   request.body.file("file").map { file =>
      val filename = file.filename
      val contentType = file.contentType
      file.ref.moveTo(new File("c:\\tmp\\uploaded\\filetest.csv"))
    }

    Ok("file uploaded at " + new java.util.Date())

 }

但是地图是空的。 这是我在前两个println语句中得到的:

multipart / form-data MultipartFormData(Map(),Vector(FilePart(file,hello2.csv,Some(application / vnd.ms-excel),TemporaryFile(C:\\ Users \\ BUSINE〜1 \\ AppData \\ Local \\ Temp \\ playtemp2236977636541678879) \\ multipartBody2268668511935303172asTemporaryFile)))),Vector())

表示我正在接收某些东西,但是我无法提取它。 有任何想法吗?

angularjs playframework playframework-2.0 ng-file-upload playframework-2.5
1个回答
1
投票

也许有些冗长,但却可以满足您的要求。
请注意,我在Mac上,因此您可能必须更改copyFile/tmp/uploaded/路径,因为它看起来就像在Windows上一样。

package controllers

import java.io.File
import java.nio.file.attribute.PosixFilePermission._
import java.nio.file.attribute.PosixFilePermissions
import java.nio.file.{Files, Path}
import java.util
import javax.inject._

import akka.stream.IOResult
import akka.stream.scaladsl._
import akka.util.ByteString
import play.api._
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.MessagesApi
import play.api.libs.streams._
import play.api.mvc.MultipartFormData.FilePart
import play.api.mvc._
import play.core.parsers.Multipart.FileInfo

import scala.concurrent.Future
import java.nio.file.StandardCopyOption._
import java.nio.file.Paths

case class FormData(filename: String)

// Type for multipart body parser     
type FilePartHandler[A] = FileInfo => Accumulator[ByteString, FilePart[A]]

val form = Form(mapping("file" -> text)(FormData.apply)(FormData.unapply))

private def deleteTempFile(file: File) = Files.deleteIfExists(file.toPath)

// Copies temp file to your loc with provided name
private def copyFile(file: File, name: String) =
    Files.copy(file.toPath(), Paths.get("/tmp/uploaded/", ("copy_" + name)), REPLACE_EXISTING)

// FilePartHandler which returns a File, rather than Play's TemporaryFile class
private def handleFilePartAsFile: FilePartHandler[File] = {
    case FileInfo(partName, filename, contentType) =>
      val attr = PosixFilePermissions.asFileAttribute(util.EnumSet.of(OWNER_READ, OWNER_WRITE))
      val path: Path = Files.createTempFile("multipartBody", "tempFile", attr)
      val file = path.toFile
      val fileSink: Sink[ByteString, Future[IOResult]] = FileIO.toPath(file.toPath())
      val accumulator: Accumulator[ByteString, IOResult] = Accumulator(fileSink)
      accumulator.map {
        case IOResult(count, status) =>
          FilePart(partName, filename, contentType, file)
      } (play.api.libs.concurrent.Execution.defaultContext)
  }

// The action
def doUpload = Action(parse.multipartFormData(handleFilePartAsFile)) { implicit request =>
    val fileOption = request.body.file("file").map {
      case FilePart(key, filename, contentType, file) =>
        val copy = copyFile(file, filename)
        val deleted = deleteTempFile(file)  // delete original uploaded file after we have 
        copy   
    }
    Ok(s"Uploaded: ${fileOption}")
}
© www.soinside.com 2019 - 2024. All rights reserved.