12

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")

いくつかの問題を除いて、ほとんど問題ありません。

  1. ファイルの最大サイズは約2メガバイトです。修正はありますが、これを行う正しい方法ですか?私の修正は、次のように、私のアプリのYesodインスタンスのmaximumContentLengthメソッドのデフォルトの実装をオーバーライドしています。

    maximumContentLength _(Just(FileNewR _))= 2 * 1024 * 1024*1024-2ギガバイトmaximumContentLength__ = 2 * 1024*1024-2メガバイト

  2. 使用されるメモリの量は、ファイルのサイズと同じです。これは本当に最適ではありません。http://hackage.haskell.org/packages/archive/wai-extra/1.2.0.4/doc/html/Network-Wai-Parse.htmlのtempFileBackEndを使用したいのですが、実際に配線する方法がわかりません。私のリクエストに入れて、フォームロジック(非表示の_tokenフィールドなど)で動作するようにします。

  3. アップロードは「シングルショット」です。Flash/Html5ベースのアップローダーでユーザーに進行状況を表示する方法の例はありますか?

4

1 に答える 1

11
  1. あなたの解決策は正しいです。maximumContentLength設定の目的は、より大きなアップロードが必要な特定のルートに対してこの値をオーバーライドできるようにすることです。

  2. これは、yesod-coreでのファイル処理の現在の設定の欠点です。現在、メモリ内ファイルアップロードを使用するようにハードコーディングされています。過去にメーリングリストでこれは最適ではないと話し合った。このためにGithubの問題を作成しました。修正は、Yesod 1.1に含まれます(ただし、リリースのスケジュールはありません)。

  3. 申し訳ありませんが、この例はありません。

于 2012-06-05T02:58:05.890 に答える