繁体   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