簡體   English   中英

使用Angular ng-file-upload上傳Scala Play Framework圖像

[英]Scala Play Framework image upload with Angular ng-file-upload

我在前端使用Angular ng-file-uploadhttps://github.com/danialfarid/ng-file-upload )管理文件上傳過程。

不幸的是,表單包含具有多個文件的復雜對象。 使用服務器端的MultipartFormDatahttps://www.playframework.com/documentation/2.5.x/ScalaBodyParsers ),我已經成功分解了上傳的內容,並且可以從request.body讀取它。

現在,令我驚訝的是,我沒有一個簡單的Json Objects ,而是一個奇怪地形成的數據類型,在ng-file-upload網站上描述為:

(...)服務器實現期望使用.key或[key]格式的嵌套數據對象鍵。 示例:數據:{記錄:{名稱:'N',圖片:文件}}發送為:記錄[名稱]-> N,記錄[圖片]->文件
數據:{記錄:{名稱:'N',圖片:文件},對象關鍵字:'。k'}發送為:記錄名稱-> N,記錄圖片->文件

到目前為止,我已經設法使用DataPartFilePart將所有數據轉換為通用的MultipartFormData.Part類型:

 val opts = body.dataParts.map {
   case (key, values) => DataPart(key, values.head)
 }

 val parts = opts ++ body.files

因此,我現在有一個非常不幸的Iterable[Part]

0 = {MultipartFormData$DataPart@86271} "DataPart(arabic[active],false)"
1 = {MultipartFormData$DataPart@86273} "DataPart(english[active],true)"
2 = {MultipartFormData$DataPart@86277} "DataPart(english[url],2132132132)"
...
7 = {MultipartFormData$FilePart@76473} "FilePart(english[image],fb_icon_325x325.png,Some(image/png),TemporaryFile(/tmp/playtemp5909927824995768544/multipartBody8348573128070542611asTemporaryFile))"

每個對象name包含其Json結構的key及其相應的value 現在,我想將其解析為對象而不是key[level1][level2]

case class PcBanner(english: PcBanners, arabic: PcBanners, kurdish: PcBanners)
case class PcBanners(active: Boolean, url: Option[String], image: Option[String])`

我希望你有主意。

問題

我知道我可以嘗試解析name字符串以使其適合對象,但是我相信中間還是有一個錯誤。 有沒有一種方法可以使用字段名稱作為參考來將此結構解析為對象? 播放功能有內置功能嗎?

感謝幫助!

正如我在標題中所述,我的情況是發送圖像 如您所料,我還將展示一個預覽以及當前保存在數據庫中的文件。

考慮到所有優點和缺點,我決定以兩種方式均以JSON格式發送所有數據。 這意味着圖像將以JSON結構進行編碼和發送。

盡管上述解決方案看起來非常方便,但實際上在實施過程中會產生新的問題。

  1. 您將很快超過服務器的POST請求大小限制。 對於Play服務器,可以擴展默認100kB,但是...
  2. 我很快遇到了一些數據格式錯誤,因為保存為巨大字節字符串的圖像可能存在一些發送/解析錯誤。

對於這個錯誤的解決方案,我不會使用更深的含義,而是使用@danial建議:

沒有像這樣單獨發送文件
{file: file, otherData: JSON.stringify(myData)}

我的解決方案

如果有人想使用類似的方法來挖掘我的答案。 在前端,我決定使用ng-file-upload庫。 它具有結合到HTML組件ngf-selectngf-drop這使得部件:

<div ngf-drop ngf-select
     ng-model="image"
     ngf-accept="'image/*'"
     ngf-resize="{width: {{width}}, height: {{height}}, quality: 1.0, restoreExif: false}">

    <img ng-show="!!image && !!image.$ngfName" ngf-src="image">

    <img ng-show="(!image || !image.$ngfName)" ng-src="{{ imageUrl }}">
</div>

在上載標簽中,我放置了圖像預覽。 這可以完美地工作。 如果未選擇圖像,則使用保存在數據庫中的圖像。

數據和圖像不再共享模型。 上傳功能如下:

return Upload.upload({
    url: url,
    data: {file: images, data: angular.toJson(data)}
}).then(function (resp) {
    console.log(resp);
}, function (error) {
    console.log(error);
});

將以上所有內容放在一起,便得到了輸出數據對象:

{  
   "english":{  
      "active":true,
      "url":"http://google.com"
   },
   "arabic":{  
      "active":true,
      "url":"http://google.com"
   },
   "kurdish":{  
      "active":true,
      "url":"http://google.com"
   }
}

在服務器端,JSON與准備好的case類匹配,並使用內置的Jackson解析器進行解析,從而簡化了對象操作。 該圖像必須手動選擇:

val json = r.body.dataParts("data")
val jsValue = Json.parse(json.head)
val result = jsValue.validate(LocalizedBanner.dataModelFormat) // parse JSON

可以使用內置函數.file從主體中提取文件:

val key = s"file[${lang.name}][${imageType.name}]"
body.file(key).map(mp => (mp.ref.file, imageType))

請享用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM