2016-09-13 147 views
0

我正在創建一個圖像上傳API,用於接收POST請求的文件。下面的代碼:在播放框架2.5中獲取上傳的文件名稱

def upload = Action(parse.temporaryFile) { request => 
    val file = request.body.file 
    Ok(file.getName + " is uploaded!") 
    } 

的file.getName返回類似:requestBody4386210151720036351asTemporaryFile

的問題是我怎麼能得到原始文件名,而不是這個臨時的名字?我檢查了標題。沒有什麼。我想我可以讓客戶端在頭文件中傳遞文件名。但是,原始文件名應該包含在請求的某個地方嗎?

回答

2

所有parse.temporaryFile體解析器不會是存儲從原始字節身體a是服務器上的本地臨時文件。正如通常所理解的那樣,它在「文件上傳」方面沒有語義。爲此,您需要確保所有其他信息都以查詢參數的形式發送,或者(更典型地)處理multipart/form-data請求,這是瀏覽器發送文件的標準方式(以及其他表單數據)。

對於這一點,你可以使用parse.multipartFormData體解析器像這樣,假設提交表單與文件字段名「形象」:

def upload = Action(parse.multipartFormData) { request => 
    request.body.file("image").map { file => 
    Ok(s"File uploaded: ${file.filename}") 
    }.getOrElse { 
    BadRequest("File is missing") 
    } 
} 

Relevant documentation

+0

它工作。得到了原始文件名。 – yang

1

默認情況下不發送。您需要從瀏覽器中專門發送。例如,對於輸入標記,files屬性將包含選定文件的數組,files[0].name包含第一個(或唯一)文件的名稱。 (我發現除name之外還有其他屬性,但它們可能會因瀏覽器而有所不同,並且我沒有玩過它們。)使用更改事件將文件名存儲在某處,以便您的控制器可以檢索它。例如,我有一些jQuery的CoffeeScript的像

$("#imageFile").change -> 
     fileName=$("#imageFile").val() 
     $("#imageName").val(fileName) 

value屬性還包含一個版本的文件名,但包括路徑(這應該是像「C:\ fakepath」出於安全原因,除非該網站是一個「值得信賴」網站AFAIK。)

(更多信息和例子比比皆是,W3 SchoolsSO: Get Filename with JQuerySO: Resolve path nameSO: Pass filename例如)

0

作爲一個例子,這會將原始文件名打印到控制檯並在視圖中返回。

def upload = Action(parse.multipartFormData(handleFilePartAsFile)) { implicit request => 

    val fileOption = request.body.file("filename").map { 

     case FilePart(key, filename, contentType, file) => 
     print(filename) 
     filename 
    } 
    Ok(s"filename = ${fileOption}") 
    } 

    /** 
    * Type of multipart file handler to be used by body parser 
    */  
    type FilePartHandler[A] = FileInfo => Accumulator[ByteString, FilePart[A]] 

    /** 
    * A 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) 
    }