我想用Yesod应用程序实现大文件上传。现在我有:
module Handler.File where
import Import
import System.Random
import System.FilePath
import Control.Monad
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text.Encoding
-- upload
uploadDirectory :: FilePath -- FIXME: make this configurable
uploadDirectory = "incoming"
randomFileName :: IO FilePath
randomFileName = do
fname'base <- replicateM 20 (randomRIO ('a','z'))
let fname = uploadDirectory </> fname'base <.> "bin"
return fname
fileUploadForm :: Form (FileInfo, Textarea)
fileUploadForm = renderDivs $ (,)
<$> fileAFormReq "Choose a file"
<*> areq textareaField "What's on the file?" Nothing
getFileNewR :: Handler RepHtml
getFileNewR = do
(formWidget, formEnctype) <- generateFormPost fileUploadForm
defaultLayout $ do
setTitle "Upload new file."
$(widgetFile "file-new")
postFileNewR :: Handler RepHtml
postFileNewR = do
user <- requireAuth
((result, formWidget), formEnctype) <- runFormPost fileUploadForm
case result of
FormSuccess (fi,info) -> do
fn <- liftIO randomFileName
liftIO (LBS.writeFile fn (fileContent fi))
let newFile = File (entityKey user) fn info (fileName fi) (fileContentType fi)
fid <- runDB $ insert newFile
redirect (FileViewR fid)
_ -> return ()
defaultLayout $ do
setTitle "Upload new file."
$(widgetFile "file-new")
除了几个问题外,它几乎没问题:
文件的最大大小约为2兆字节。我有一个修复,但这是正确的方法吗?我的修复是覆盖我的应用程序的Yesod实例中的maximumContentLength方法的默认实现,如下所示:
maximumContentLength _(Just(FileNewR _))= 2 * 1024 * 1024 * 1024 - 2千兆字节 maximumContentLength _ _ = 2 * 1024 * 1024 - 2兆字节
使用的内存量等于文件的大小。这真的不是最理想的。我想使用来自http://hackage.haskell.org/packages/archive/wai-extra/1.2.0.4/doc/html/Network-Wai-Parse.html的tempFileBackEnd,但我不知道如何将其实际连接到我的请求中并使其与表单逻辑(隐藏_token字段等)一起使用。
上传是单拍&#39;:如何使其适用于向用户显示进度的基于Flash / Html5的上传器的任何示例?
答案 0 :(得分:11)
您的解决方案是正确的。 maximumContentLength设置的目的是允许您为需要更大上载的特定路由覆盖此值。
这是yesod-core中当前文件处理设置的缺点。它目前硬编码使用内存文件上传。我们在过去的邮件列表中讨论过这不是最理想的。我刚为此创建了一个Github issue,修复程序将包含在Yesod 1.1中(虽然没有发布时间表)。
我没有这方面的例子,抱歉。