2019年5月14日火曜日

YesodのFileInfoにハマった

Yesodでアップロードファイルを扱うのにFileInfo型を使うんだけどこれ


data FileInfo = FileInfo {
    fileName :: !Text,
    fileContentType :: !Text,
    fileSourceRaw :: !(ConduitT () ByteString (ResourceT IO) ()),
    fileMove :: !(FilePath -> IO ())
}

これのfileSourceRawなんだが、こうやってとってみると[ByteString]がでてくる


bss <- sourceToList $ fileSource finfo

でたまたまこれをbase64化すればhtmlのimgタグで見れるかとおもいこうやってTextへ変換してhamletテンプレートに出力してみた

import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Char8 as C
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8)
...
byteString2Base64 :: [ByteString] -> T.Text
byteString2Base64 = decodeUtf8 . B64.encode . C.unwords

これで吐かれたテキストを


<img src="data:#{contentType};base64,#{b64img}" class="img-fluid mx-auto d-block" alt="">

b64imgにbase64のTextが流れてくが、これが甘い



これだと出力される画像が途中で腐ってしまう、しばらくハマる...よくよく調べてみると、こんなのあった


fileSourceByteString!!

Yesod.Core.Handlerで定義されテイルではないですか、、、やりたかったことそのまんま。

気になったので実装みてみたら....


fileSourceByteString :: MonadResource m => FileInfo -> m S.ByteString
fileSourceByteString fileInfo = runConduit (L.toStrict <$> (fileSource fileInfo .| sinkLazy))

なんか、CombinatorsでつなげてLazyをStrictに直してるようにしか見えないけど、sourceToListを使った方法との違いが分からない。

まぁ結果オーライとします。

2019年4月26日金曜日

悪い予感が的中したよ

今日は朝出てくるときに、嫌な感じがしたが、的中した。


初めは洒落てた、


どこかの国の洒落たびー


だから何だよ、結局、これ


そして、帰りたい


自力でいけるか、長い


やることなくなって結局こうなる。


長いGW開始したけど、皆さんお元気で.....

2019年4月25日木曜日

haskellの例外処理

多分よく分かってない

今日は割り込みによって例外が発生し、ビールを買ってしまいました、みたいな帰宅モナドのなかの話。



bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket :: (とりあえずやってみろ) -> (ダメだイケてなかったから何とかしろ) -> (とりあえずがイケてるならやれ) -> IO (うまくいった結果よこせ)

try..cache..finally みたいなやつです

getFileMimeType :: String -> IO (Maybe ImageContents)
getFileMimeType file = do
    magic <- magicOpen [MagicMimeType]
    magicLoadDefault magic
    mt <- try $ magicFile magic file
    case mt of
        Left (err::IOException) -> return Nothing
        Right mimeType -> do
            contents <- bracket (openFile file ReadMode) hClose hGetContents
            return $ return $ ImageContents { unMimeType = packChars mimeType, unImageBuff = contents }

ちなみにLeft (err::IOException)がScopedTypeVariables拡張が必要らしいです。