# Helpers (https://s3.dimah.dev/docs/react/helpers)



`@dimah-s3/react` and `@dimah-s3/core` export utilities for formatting file sizes, progress labels, hashing, and error localization.

## Progress and speed formatting [#progress-and-speed-formatting]

```ts
import { formatUploadProgress, formatSpeed, formatEta } from "@dimah-s3/react";

formatUploadProgress(1_200_000, 2_000_000, 60); // "1.2 MB / 2 MB (60%)"
formatSpeed(1_200_000); // "1.2 MB/s"
formatEta(800_000, 200_000); // "4s"
```

***

## File size and validation [#file-size-and-validation]

```ts
import { formatFileSize, truncateFileName, validateFile } from "@dimah-s3/core";

formatFileSize(1_500_000); // "1.4 MB"
truncateFileName("my-avatar-profile-picture-long-name.png", 20); // "my-avatar-pro… .png"

const error = validateFile(file, {
  accept: ["image/*"],
  maxFileSize: 2 * 1024 * 1024,
});
// returns null if valid, or { code: "FILE_TYPE_NOT_ALLOWED", message }
```

***

## Checksums and public URLs [#checksums-and-public-urls]

```ts
import {
  buildPublicObjectUrl,
  matchesMagicBytes,
  sha256File,
} from "@dimah-s3/core";

// SHA-256 base64 digest
const hash = await sha256File(file);

// Public CDN URL helper
const url = buildPublicObjectUrl({
  baseUrl: "https://cdn.example.com",
  key: "avatar/uuid/avatar.png",
});
```

## Frequently asked questions [#frequently-asked-questions]

<Accordions>
  <Accordion title="How do I format API errors in toast notifications?">
    Use `useFormatDimahError`:

    ```tsx
    import { isAPIError, useFormatDimahError } from "@dimah-s3/react";

    export function AvatarUploader() {
      const formatError = useFormatDimahError();

      const upload = useUpload({
        route: "avatar",
        onError: (err) => {
          toast.error(formatError(err));
        },
      });
    }
    ```
  </Accordion>
</Accordions>
