1

我想用 Lift 上传一张图片,并立即在页面的某些元素中显示它,而无需重新加载。我想在这个解决方案(使用 PHP)中这样做。

那里的过程比较简单。我用一个虚拟的 HTML 片段替换了 PHP 文件:

<form id="imageform" method="post" enctype="multipart/form-data" action="ajaximage.html">
    <input id="imageFile" name="imageFile" type="file" size="50" maxlength="100000"/>
</form><br/>

<script src="jquery-1.8.3.min.js"></script>
<script src="jquery.form.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        $('#imageFile').live('change', function() {
            $("#preview").html('');
            $("#preview").html('<img src="images/processing.jpg" alt="Uploading...."/>');
            $("#imageform").ajaxForm({
                target : '#preview'
            }).submit();
        });
    });
</script>

HTML 片段:

<img src="images/someimage.jpg"/>

嗯,这行得通。但我显然需要动态行为。示例页面使用 PHP 文件代替我的 HTML 片段,该文件从请求中提取数据,将其保存在服务器中,并相应地输出预览图像的 HTML -echo "<img src='uploads/".$actual_image_name."' class='preview'>";

现在,我不知道如何使用 Lift 来实现这一点。

我发现了这个讨论:https ://groups.google.com/forum/?fromgroups=#!topic/liftweb/6bxNlbBPJvE但是除了对我不想使用的框架和 HTML5 东西的模糊建议之外,没有好的解决方案.


第 2 部分。我已经在 Lift 中实现了一些基础知识:

HTML:

<div class="lift:AddImage.addEntry" form="POST" multipart="true">
        <p><prefix:imageUpload/></p>
        <p><prefix:test/></p>
</div>

片段:

package code 
package snippet

import net.liftweb.http.S
import net.liftweb.common.Full
import net.liftweb.common.Empty
import net.liftweb.common.Box
import net.liftweb.http.FileParamHolder
import net.liftweb.util._
import Helpers._
import scala.xml.Group
import scala.xml.NodeSeq
import net.liftweb.http.SHtml
import javax.annotation.Resource
import java.io.OutputStream
import java.io.FileOutputStream

class AddImage {

  // Add a variable to hold the FileParamHolder on submission
  var fileHolder : Box[FileParamHolder] = Empty

  def submitTest () {
    println("submitTest called!")

    val receiptOk = fileHolder match {
      // An empty upload gets reported with a null mime type,
      // so we need to handle this special case
      case Full(FileParamHolder(_, null, _, _)) => true

      case Full(FileParamHolder(_, mime, _, data)) =>

        println("MIME: " + mime)

        if (mime.startsWith("image/")) {

            println("uploading the image: ")

            //scala.io.Source.fromBytes(data)
            try {
                val out: OutputStream = new FileOutputStream("test.jpg");
                out.write(data);
                out.flush();
                out.close();

            } catch {
              case e: Exception => println("Exception!: " + e)
            }

          true
        }

      case Full(_) => {
        S.error("Invalid attachment")
        false
      }

      case _ => true
    }

//    (e.validate, receiptOk) match {
//    }
}

  def addEntry(content: NodeSeq): NodeSeq = {

      bind("prefix", content,
              "imageUpload" -> SHtml.fileUpload(f => fileHolder = Box !! f),
              "test" -> SHtml.submit("submitz", submitTest))
  }
}

但我被困在这里是因为:

  • 我不知道如何从 jquery 引用 Lift 创建的表单。

  • javascript 在上传输入字段更改时提交表单,并在元素ajaxForm()中插入 PHP 脚本的结果。#preview我不知道如何在 scala 中提交表单并进一步输出图像 HTML,以便可以将其插入#preview

希望这不是太多问题:) 提前谢谢。

4

1 回答 1

1

这不是一个完整的答案,而是一堆可以帮助您解决问题的指针。

为了将 JS 附加到您的表单,我认为您应该能够向表单添加一个 id 属性并以这种方式附加到它。如果由于某种原因这对您不起作用,一个简单的解决方法是用 div 包装表单,例如:

<div id="wrapper"><form> ... </form></div>

然后您可以使用 jquery 来获取它,例如:$('#wrapper form'). 这里有一篇关于 ajax 文件上传和 Lift 的 wiki 文章:https ://www.assembla.com/spaces/liftweb/wiki/AJAX_File_Upload 。它还使用 jQuery 方法来重定向表单提交,因此您可能会从中获得一些见解。

关于实际显示图像数据,有一些功能可能会派上用场。第一个是JsCmds.SetHtml,另一个是S.fmapFunc

JsCmds.SetHtml(id:String, replacement:NodeSeq)将允许您将与特定 id 匹配的 html 元素的内容替换为提供的NodeSeq.

S.fmapFunc将允许您创建一个可以返回图像的函数。在下面的示例中,您将创建一个函数,该函数将图像读取到字节数组中,然后将其输出到浏览器,并为其赋予唯一的 id。第二部分返回一个引用唯一 id 的对象并对其进行处理(在本例中为 XML 元素)。因此,下面的示例将返回一个调用您的图像的图像标记。

   S.fmapFunc(() => {
       val mimeType:String = //set mimeType
       val data:Array[Byte] = //get byte array of image
       throw ResponseShortcutException.shortcutResponse(
           InMemoryResponse(data, 
              ("Content-Type" -> mimeType) :: Nil, Nil, 200))
   }) { 
       name => <img src={"?" + name + "=_"} />
   }

这是使用InMemoryResponse,这可能并不理想,具体取决于您的图像有多大。你也可以使用StreamingResponse

将两者结合使用,您应该生成包含指向可以在页面上显示的图像的链接的 Html。可能有很多方法可以完成这项工作,因此毫无疑问,您将能够获得所需的工作。Ajax 文件上传可能有点棘手,所以让所有东西一起工作可能需要一些工作,但希望这可以为您指明正确的方向。

此外,作为旁注,电梯问题最活跃的地方是他们的邮件列表:liftweb@googlegroups.com。有很多人在监控它,包括项目的提交者,他们反应非常迅速。

于 2012-12-26T15:11:12.857 回答