DocuSign.FileDownloader (DocuSign v3.3.0)

Copy Markdown View Source

File download utilities for DocuSign documents and attachments.

This module provides functionality for downloading files from DocuSign APIs with automatic filename extraction from Content-Disposition headers, flexible file handling options, and support for multiple file formats.

Features

  • Automatic filename extraction from Content-Disposition headers
  • Configurable temporary file management
  • Multiple download strategies (to file, to memory, streaming)
  • Support for various file formats (PDF, HTML, images, etc.)
  • Filename sanitization and collision handling
  • Content-Type detection and validation

Usage

# Download to a temporary file
{:ok, path} = DocuSign.FileDownloader.download_to_temp(conn, url)

# Download to a specific path
{:ok, path} = DocuSign.FileDownloader.download_to_file(conn, url, "/path/to/file.pdf")

# Download to memory
{:ok, {content, filename, content_type}} = DocuSign.FileDownloader.download_to_memory(conn, url)

# Download with options
{:ok, result} = DocuSign.FileDownloader.download(conn, url,
  strategy: :file,
  filename: "custom_name.pdf",
  temp_dir: "/custom/temp"
)

Configuration

You can configure the file downloader options:

config :docusign, :file_downloader,
  max_filename_length: 255,
  sanitize_filenames: true,
  allowed_content_types: ~w(application/pdf text/html image/png image/jpeg),
  track_temp_files: true

Summary

Functions

Cleans up tracked temporary files.

Downloads a file from the given URL using the DocuSign connection.

Downloads a file to a specific path.

Downloads a file to memory.

Downloads a file to a temporary location.

Generates a unique filename by appending a number if the file already exists.

Extracts filename from Content-Disposition header.

Sanitizes a filename by removing invalid characters and path components.

Types

download_options()

@type download_options() :: [
  strategy: download_strategy(),
  filename: String.t() | nil,
  temp_options: keyword() | nil,
  max_size: non_neg_integer() | nil,
  validate_content_type: boolean(),
  overwrite: boolean()
]

download_result()

@type download_result() ::
  {:ok, binary()}
  | {:ok, {binary(), String.t(), String.t()}}
  | {:ok, String.t()}
  | {:error, term()}

download_strategy()

@type download_strategy() :: :file | :memory | :temp | :stream

Functions

cleanup_temp_files()

@spec cleanup_temp_files() :: :ok

Cleans up tracked temporary files.

This function calls Temp.cleanup/0 to remove all tracked temporary files. Useful for manual cleanup before process exit.

Examples

DocuSign.FileDownloader.cleanup_temp_files()

download(conn, url, opts \\ [])

Downloads a file from the given URL using the DocuSign connection.

Options

  • :strategy - Download strategy (:file, :memory, :temp, :stream)
  • :filename - Custom filename (overrides Content-Disposition)
  • :temp_options - Options passed to Temp library for temporary files
  • :max_size - Maximum file size in bytes
  • :validate_content_type - Whether to validate content type
  • :overwrite - Whether to overwrite existing files

Returns

  • {:ok, content} when strategy is :memory
  • {:ok, {content, filename, content_type}} when strategy is :memory with metadata
  • {:ok, filepath} when strategy is :file or :temp
  • {:error, reason} on failure

Examples

# Download envelope document to temporary file
{:ok, temp_path} = DocuSign.FileDownloader.download(conn,
  "/v2.1/accounts/123/envelopes/456/documents/1")

# Download with custom temp options
{:ok, path} = DocuSign.FileDownloader.download(conn, url,
  temp_options: [prefix: "contract", suffix: ".pdf"])

# Download to memory for processing
{:ok, {content, filename, content_type}} = DocuSign.FileDownloader.download(conn, url,
  strategy: :memory)

download_to_file(conn, url, filepath, opts \\ [])

@spec download_to_file(DocuSign.Connection.t(), String.t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, term()}

Downloads a file to a specific path.

Returns {:ok, filepath} on success.

Examples

{:ok, path} = DocuSign.FileDownloader.download_to_file(conn, url, "/path/to/save/document.pdf")

download_to_memory(conn, url, opts \\ [])

@spec download_to_memory(DocuSign.Connection.t(), String.t(), keyword()) ::
  {:ok, {binary(), String.t(), String.t()}} | {:error, term()}

Downloads a file to memory.

Returns {:ok, {content, filename, content_type}} on success.

Examples

{:ok, {pdf_content, "document.pdf", "application/pdf"}} =
  DocuSign.FileDownloader.download_to_memory(conn, url)

download_to_temp(conn, url, opts \\ [])

@spec download_to_temp(DocuSign.Connection.t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, term()}

Downloads a file to a temporary location.

Returns {:ok, filepath} on success, where filepath is the path to the temporary file. The caller is responsible for cleaning up the temporary file.

Examples

{:ok, temp_path} = DocuSign.FileDownloader.download_to_temp(conn, url)
content = File.read!(temp_path)
File.rm!(temp_path)  # Clean up

ensure_unique_filename(filepath)

@spec ensure_unique_filename(String.t()) :: String.t()

Generates a unique filename by appending a number if the file already exists.

Examples

# If document.pdf exists, returns document_1.pdf
# If document_1.pdf also exists, returns document_2.pdf, etc.
DocuSign.FileDownloader.ensure_unique_filename("/path/to/document.pdf")

extract_filename_from_header(content_disposition)

@spec extract_filename_from_header(String.t()) ::
  {:ok, String.t()} | {:error, :no_filename}

Extracts filename from Content-Disposition header.

Examples

iex> DocuSign.FileDownloader.extract_filename_from_header("attachment; filename=document.pdf")
{:ok, "document.pdf"}

iex> DocuSign.FileDownloader.extract_filename_from_header("attachment; filename*=UTF-8''document%20name.pdf")
{:ok, "document name.pdf"}

iex> DocuSign.FileDownloader.extract_filename_from_header("attachment")
{:error, :no_filename}

sanitize_filename(filename)

@spec sanitize_filename(String.t()) :: String.t()

Sanitizes a filename by removing invalid characters and path components.

Examples

iex> DocuSign.FileDownloader.sanitize_filename("../../malicious.pdf")
"malicious.pdf"

iex> DocuSign.FileDownloader.sanitize_filename("file<>:"|?*.pdf")
"file.pdf"