Documentation
supastarter for Nuxtsupastarter for NuxtStorage

Accessing stored files

Learn how to access and download files stored in your supastarter application.

In the previous step you learned how to upload files to your storage provider. At this point, these uploaded files are not accessible to anyone including the user that uploaded them.

This behavior is by design as we want to control the access to the files in the API layer of the application.

So in this step you will learn how to make these files accessible to the user(s) that should be allowed to access them.

Accessing the files

To access the files, you need to create a signed URL for the file.

All you need to do is to call the getSignedUrl function from the storage package.

import { getSignedUrl } from "@repo/storage";
import { config as storageConfig } from "@repo/storage/config";

const signedUrl = await getSignedUrl(filePath, {
    bucket: storageConfig.bucketNames.documents,
    expiresIn: 60 * 60, // set the expiration to what makes sense for your use case
});

The returned URL can then be used to access the file from the browser and will be valid for the duration you set.

Note: The signed URL will work for everyone that has access to the URL, so be careful with the expiration time and who you output the signed URL to.

With this you could for example create a download endpoint in your API that checks the permission of the user and creates a signed URL for the file.

packages/api/src/routes/documents.ts
import { config as storageConfig } from "@repo/storage/config";

export const documentsRouter = new Hono().basePath("/documents").get(
	"/download",
	authMiddleware,
	validator(
		"query",
		z.object({
			fileId: z.string().min(1),
		}),
	),
	async (c) => {
		const { fileId } = c.req.valid("query");
        const user = c.get("user");

		// ... get the file path from the database by the provided fileId
        // ... check with the `user` object if the user has access to the file

		const signedUrl = await getSignedUrl(filePath, {
            bucket: storageConfig.bucketNames.documents,
            expiresIn: 60,
        });

        return c.json({ signedUrl });
	},
);

Then you can fetch the signed URL from the frontend and open it to download the file.

<script setup lang="ts">
const downloadFile = async (fileId: string) => {
  const { signedUrl } = await $orpcClient.documents.download({ fileId });
  window.open(signedUrl, '_blank');
};
</script>

<template>
  <UButton @click="downloadFile(fileId)">Download</UButton>
</template>