Chcę zaimplementować przesyłanie dużych plików za pomocą aplikacji Yesod. Teraz mam:Efektywne przesyłanie dużych plików za pomocą 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")
Jest przeważnie w porządku, z wyjątkiem kilku problemów:
Maksymalny rozmiar pliku jest około 2 megabajtów. Mam poprawkę, ale czy jest to właściwy sposób na zrobienie tego? Moja poprawka jest nadrzędne domyślną implementację metody maximumContentLength na przykład Yesod dla mojej aplikacji, na przykład:
maximumContentLength _ (Tylko (FileNewR _)) = 2 * 1024 * 1024 * 1024 - 2 gigabajty maximumContentLength _ _ = 2 * 1024 * 1024 - 2 megabajty
Ilość wykorzystanej pamięci jest równa wielkości pliku. To jest naprawdę nieoptymalne. Chciałbym użyć tempFileBackEnd z http://hackage.haskell.org/packages/archive/wai-extra/1.2.0.4/doc/html/Network-Wai-Parse.html, ale nie mam pojęcia, jak faktycznie podłączyć go do mojej prośby i sprawić, by działał z logiką formularzy (ukryte pole wpisane itd.).
Przesyłanie to "pojedyncze ujęcie": przykłady, jak sprawić, aby działał on z przesyłającymi treści Flash/HTML5, które pokazują postępy dla użytkownika?