1 changed files with 85 additions and 0 deletions
@ -0,0 +1,85 @@ |
|||||
|
/** |
||||
|
* Image URL Utilities |
||||
|
* |
||||
|
* Functions for uploading images to the local server and generating |
||||
|
* URLs that external providers can fetch from. |
||||
|
* |
||||
|
* Usage: |
||||
|
* 1. Check if image should use URL: shouldUseImageUrl(base64DataUrl) |
||||
|
* 2. Upload and get URL: const { url, id } = uploadImageForUrl(base64, baseUrl) |
||||
|
* 3. Pass URL to provider |
||||
|
* 4. Clean up after provider fetches: deleteImage(id) |
||||
|
*/ |
||||
|
|
||||
|
import { storeImage } from "./store"; |
||||
|
|
||||
|
// Re-export store functions for convenience
|
||||
|
export { |
||||
|
storeImage, |
||||
|
getImage, |
||||
|
deleteImage, |
||||
|
deleteImages, |
||||
|
getStoreStats, |
||||
|
} from "./store"; |
||||
|
|
||||
|
/** |
||||
|
* Size threshold for using URL instead of base64 (256KB) |
||||
|
* Replicate recommends URLs for files larger than this |
||||
|
*/ |
||||
|
const URL_SIZE_THRESHOLD_BYTES = 256 * 1024; |
||||
|
|
||||
|
/** |
||||
|
* Upload an image to the local store and return its URL |
||||
|
* |
||||
|
* @param base64DataUrl - Image as base64 data URL |
||||
|
* @param baseUrl - Server base URL (e.g., "http://localhost:3000") |
||||
|
* @returns Object containing full URL and image ID for cleanup |
||||
|
* |
||||
|
* @example |
||||
|
* const { url, id } = uploadImageForUrl(imageData, "http://localhost:3000"); |
||||
|
* // url: "http://localhost:3000/api/images/abc-123"
|
||||
|
* // Use URL with provider, then clean up:
|
||||
|
* deleteImage(id); |
||||
|
*/ |
||||
|
export function uploadImageForUrl( |
||||
|
base64DataUrl: string, |
||||
|
baseUrl: string |
||||
|
): { url: string; id: string } { |
||||
|
const id = storeImage(base64DataUrl); |
||||
|
const url = `${baseUrl}/api/images/${id}`; |
||||
|
|
||||
|
return { url, id }; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Check if an image should use URL-based transfer instead of base64 |
||||
|
* |
||||
|
* Returns true if the base64 data exceeds 256KB, which is Replicate's |
||||
|
* recommended threshold for using URLs instead of data URIs. |
||||
|
* |
||||
|
* @param base64DataUrl - Image as base64 data URL |
||||
|
* @returns true if image should use URL, false if base64 is fine |
||||
|
* |
||||
|
* @example |
||||
|
* if (shouldUseImageUrl(imageData)) { |
||||
|
* const { url, id } = uploadImageForUrl(imageData, baseUrl); |
||||
|
* // use URL
|
||||
|
* } else { |
||||
|
* // use base64 directly
|
||||
|
* } |
||||
|
*/ |
||||
|
export function shouldUseImageUrl(base64DataUrl: string): boolean { |
||||
|
// Extract base64 data portion from data URL
|
||||
|
const match = base64DataUrl.match(/^data:[^;]+;base64,(.+)$/); |
||||
|
if (!match) { |
||||
|
// If not a valid data URL, default to using URL for safety
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
const base64Data = match[1]; |
||||
|
// Base64 encoded data is ~33% larger than raw binary
|
||||
|
// Calculate approximate raw size: base64Length * 3/4
|
||||
|
const approximateByteSize = (base64Data.length * 3) / 4; |
||||
|
|
||||
|
return approximateByteSize > URL_SIZE_THRESHOLD_BYTES; |
||||
|
} |
||||
Loading…
Reference in new issue