使用输入表格将数据上传到Yesod服务器

3

如何通过Yesod中的自定义输入表单正确上传文件?

我使用AngularJS开发了一个前端,并通过JSON对象在服务器和客户端之间传递数据。但是,在上传文件时,这种方式不起作用。因此,我转而使用表单。

通过收集不同的资源,我最终得到以下代码。在客户端上,我使用以下函数:

this.submitNewMeas = function() {
    var selected_file = document.getElementById('measurements').files[0];
    var fd = new FormData();
    fd.append("measurementsFile", selected_file);

    var response =  $http({
    method: 'POST',
    url: '/measurements/'+this.currMedia.id,
    headers: {
                'Content-Type': 'multipart/form-data'
    },
    data: {
                fd
    },
    transformRequest: formDataObject
    });
    ...
    };

在服务器端,我接收到的数据如下:

postMeasurementsR :: MediaId -> Handler Value
postMeasurementsR mediaId =  do
result <- runInputPost $ iopt fileField "measurementsFile"
case result of
    Just fileInfo -> do
        saveMeas fileInfo "measDir"

saveMeas :: FileInfo -> FilePath -> HandlerT App IO (FilePath)
saveMeas file dest = do
  let filename = unpack $ fileName file
      dest = dest </> filename
  liftIO $ fileMove file dest
  return filename

然而,这会导致服务器错误。
20/Nov/2014:13:40:15 +0100 [Error#yesod-core] <<loop>> @(yesod-core-1.4.3:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:502:5)
Status: 500 Internal Server Error 54.70131s

如果我不尝试保存数据,那么文件信息会被接收,并且我可以在服务器上看到文件名。
我已成功使用Yesod表单上传文件,但是当涉及自定义表单时,迄今为止所有的尝试都失败了。
非常感谢任何帮助。
谢谢。
1个回答

7
dest = dest </> filename

那就是你无限循环的源头:你在说“dest被定义为它自己加上文件名”。实际上,你正在遮蔽原始声明的dest。一个简单的解决方案是将第二个声明命名为dest'(或更好地,使用更具信息性的名称)。

1
这告诉我需要休息一下。我简直不敢相信我竟然忽略了这个!谢谢你,Michael。 - Damian Nadales
GHC选项-Wall会警告你。 - Lemming

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接