我正在尝试制作一个 Yesod Web 应用程序,允许上传文件并将其保存在临时文件夹中。我正在使用 Base64 编码/解码。当我上传包含以下内容的文本文件时:
copie carte d'identité
téléphone
autocertfication fiscale
signature
那么我在临时文件夹中得到的文件内容是:
u«Zµìmþ™ZŠvÚ±î¸copie carte d'identité
téléphone
autocertfication fiscale
signature
输入文件是UTF8编码的。
这是我如何使用 JavaScript 处理文件上传:
$("#file").on("change", function() {
let file = this.files[0];
let fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = function() {
let base64 = fileReader.result;
$.ajax({
contentType: "application/json",
processData: false,
url: "@{FileR}",
type: "PUT",
data: JSON.stringify({
_filename: file.name,
_base64: base64
}),
success: function(result) {
// not important
},
dataType: "text"
});
};
fileReader.onerror = function() {
alert(fileReader.error);
};
});
在 Haskell 中,我有:
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Char8 as BC
import System.IO.Temp ( getCanonicalTemporaryDirectory )
base64ToFile :: String -> FilePath -> IO FilePath
base64ToFile b64string fileName = do
let bstring = B64.decodeLenient (BC.pack b64string)
tmpDir <- getCanonicalTemporaryDirectory
let filePath = tmpDir ++ "/" ++ fileName
B.writeFile filePath bstring
return filePath
data File = File {
_filename :: String,
_base64 :: String
} deriving (Show, Generic)
instance FromJSON File
b64FileToFile :: File -> IO FilePath
b64FileToFile file = base64ToFile (_base64 file) (_filename file)
putFileR :: Handler String
putFileR = do
file <- requireCheckJsonBody :: Handler File
liftIO $ b64FileToFile file
我不知道问题的根源在哪里,是在 JavaScript 步骤中还是在 Haskell 步骤中。我希望能够上传文本文件、CSV 文件、XLSX 文件或图像文件。
必须从 Base64 字符串中删除 MIME 类型,即只取逗号后面的部分:
let base64 = fileReader.result.split(",")[1];