IHP Api Reference
Copyright(c) digitally induced GmbH 2021
Safe HaskellNone

IHP.FileStorage.ControllerFunctions

Description

 
Synopsis

Documentation

storeFile :: (?context :: context, ConfigProvider context) => FileInfo LByteString -> Text -> IO StoredFile Source #

Uploads a file to a directory in the storage

See storeFileWithOptions for more advanced use cases.

Example: Save a file upload by the user to the storage

action UpdateLogoAction = do
    let file = fileOrNothing "file"
            |> fromMaybe (error "No file given")

    storedFile <- storeFile file "logos"

    let url = storedFile.url

removeFileFromStorage :: (?context :: context, ConfigProvider context) => StoredFile -> IO (Either MinioErr ()) Source #

Permanently removes a previously stored file from storage.

Example: Delete a previously uploaded file. The objectPath and url are stored in the database in this example.

action DeleteUploadedFileAction { uploadedFileId } = do
    uploadedFile <- fetch uploadedFile
    let storedFile = StoredFile
            { path = uploadedFile.objectPath
            , url = uploadedFile.url
            }
    removeFileFromStorage storedFile
    deleteRecord uploadedFile
    redirectTo UploadedFilesAction

storeFileWithOptions :: (?context :: context, ConfigProvider context) => FileInfo LByteString -> StoreFileOptions -> IO StoredFile Source #

Like storeFile but with more options.

See storeFileWithOptions for more advanced use cases.

Example: Save a file to my_files directory and specify a 'Content-Disposition: attachment; filename="$filename"' header

let file = fileOrNothing "file" |> fromMaybe (error "no file given")

let options :: StoreFileOptions = def
        { directory = "my_files"
        , contentDisposition = contentDispositionAttachmentAndFileName
        }

storedFile <- storeFileWithOptions file options
let url = storedFile.url

Example: Transform an uploaded image to a JPEG file, strip meta data and store it inside the pictures directory

let file = fileOrNothing "file" |> fromMaybe (error "no file given")

let options :: StoreFileOptions = def
        { directory = "pictures"
        , preprocess = applyImageMagick "jpg" "-strip"
        }

storedFile <- storeFileWithOptions file options
let url = storedFile.url

storeFileFromUrl :: (?context :: context, ConfigProvider context) => Text -> StoreFileOptions -> IO StoredFile Source #

Fetches an url and uploads it to the storage.

The stored file has the content type provided by Content-Type header of the downloaded file.

Example: Copy a file from a remote server to the pictures directory

let externalUrl = "http://example/picture.jpg"

let options :: StoreFileOptions = def
        { directory = "pictures"
        }

storedFile <- storeFileFromUrl externalUrl options
let newUrl = storedFile.url

storeFileFromPath :: (?context :: context, ConfigProvider context) => Text -> StoreFileOptions -> IO StoredFile Source #

Uploads a local file to the storage

The content type is guessed based on the file extension.

Example: Copy a local "picture.jpg" to the pictures directory inside the storage

let options :: StoreFileOptions = def
        { directory = "pictures"
        }

storedFile <- storeFileFromPath "picture.jpg" options
let newUrl = storedFile.url

createTemporaryDownloadUrl :: (?context :: context, ConfigProvider context) => StoredFile -> IO TemporaryDownloadUrl Source #

Returns a signed url for a StoredFile. The url is valid for 7 days.

If the StaticDirStorage is used, a unsigned normal URL will be returned, as these files are public anyways.

Example: Get a signed url for a stored file using createTemporaryDownloadUrl

let file = fileOrNothing "file"
        |> fromMaybe (error "No file given")

storedFile <- storeFile file "logos"

signedUrl <- createTemporaryDownloadUrl storedFile

let url :: Text = signedUrl.url
let expiredAt :: UTCTime = signedUrl.expiredAt

createTemporaryDownloadUrlFromPath :: (?context :: context, ConfigProvider context) => Text -> IO TemporaryDownloadUrl Source #

Returns a signed url for a path inside the storage. The url is valid for 7 days.

If the StaticDirStorage is used, a unsigned normal URL will be returned, as these files are public anyways.

Example: Get a signed url for a path

signedUrl <- createTemporaryDownloadUrlFromPath "logos/8ed22caa-11ea-4c45-a05e-91a51e72558d"

let url :: Text = signedUrl.url
let expiredAt :: UTCTime = signedUrl.expiredAt

See createTemporaryDownloadUrlFromPathWithExpiredAt if you want to customize the url expiration time of 7 days.

createTemporaryDownloadUrlFromPathWithExpiredAt :: (?context :: context, ConfigProvider context) => Int -> Text -> IO TemporaryDownloadUrl Source #

Like createTemporaryDownloadUrlFromPath, but with a custom expiration time. Returns a signed url for a path inside the storage. The url is valid for 7 days.

If the StaticDirStorage is used, a unsigned normal URL will be returned, as these files are public anyways.

Example: Get a signed url for a path that expires in 5 minutes

let validInSeconds = 5 * 60
signedUrl <- createTemporaryDownloadUrlFromPathWithExpiredAt validInSeconds "logos/8ed22caa-11ea-4c45-a05e-91a51e72558d"

let url :: Text = signedUrl.url
let expiredAt :: UTCTime = signedUrl.expiredAt

refreshTemporaryDownloadUrlFromFile :: (?modelContext :: ModelContext, ?context :: context, ConfigProvider context, CanUpdate record, HasField "signedUrl" record Text, HasField "signedUrlExpiredAt" record UTCTime, HasField "path" record Text, SetField "signedUrl" record Text, SetField "signedUrlExpiredAt" record UTCTime, SetField "path" record Text) => record -> IO record Source #

Use the temporary download URL if the current one is not expired. Otherwise, create a new temporary download URL and update the record.

Example: Fetch an UploadedFile record (a custom record with signedUrl, signedUrlExpiredAt and path ) and use refreshTemporaryDownloadUrlFromFile to get a fresh signed url if expired date has passed. and update it with the signed url.

uploadedFile <- fetch uploadedFileId
uploadedFile <- refreshTemporaryDownloadUrlFromFile uploadedFile

uploadToStorage :: forall (fieldName :: Symbol) record (tableName :: Symbol). (?context :: ControllerContext, SetField fieldName record (Maybe Text), KnownSymbol fieldName, HasField "id" record (Id (NormalizeModel record)), Show (PrimaryKey (GetTableName (NormalizeModel record))), tableName ~ GetTableName record, KnownSymbol tableName, HasField "meta" record MetaBag, SetField "meta" record MetaBag) => Proxy fieldName -> record -> IO record Source #

Saves an upload to the storage and sets the record attribute to the url.

Uses the table name of the record as the upload directory (e.g. companies when saving an attachment for a Company record).

See uploadToStorageWithOptions if you want to provide custom options.

Example: Upload a logo for a Company

action UpdateCompanyAction { companyId } = do
    company <- fetch companyId
    company
        |> fill @'["name"]
        |> uploadToStorage #logoUrl
        >>= ifValid \case
            Left company -> render EditView { .. }
            Right company -> do
                company <- company |> updateRecord
                redirectTo EditCompanyAction { .. }

uploadToStorageWithOptions :: forall (fieldName :: Symbol) record (tableName :: Symbol). (?context :: ControllerContext, SetField fieldName record (Maybe Text), KnownSymbol fieldName, HasField "id" record (Id (NormalizeModel record)), Show (PrimaryKey (GetTableName (NormalizeModel record))), tableName ~ GetTableName record, KnownSymbol tableName, HasField "meta" record MetaBag, SetField "meta" record MetaBag) => StoreFileOptions -> Proxy fieldName -> record -> IO record Source #

Saves an upload to the storage and sets the record attribute to the url.

Example: Upload a logo for a Company and convert it to a 512x512 PNG

action UpdateCompanyAction { companyId } = do
    let uploadLogo = uploadToStorageWithOptions $ def
            { preprocess = applyImageMagick "png" "-resize '512x512^' -gravity north -extent 512x512 -quality 100% -strip"  }

    company <- fetch companyId
    company
        |> fill @'["name"]
        |> uploadLogo #logoUrl
        >>= ifValid \case
            Left company -> render EditView { .. }
            Right company -> do
                company <- company |> updateRecord
                redirectTo EditCompanyAction { .. }

storage :: (?context :: context, ConfigProvider context) => FileStorage Source #

Returns the current storage configured in Config.hs

storagePrefix :: (?context :: ControllerContext) => Text Source #

Returns the prefix for the storage. This is either static/ or an empty string depending on the storage.