Next.js Discord

Discord Forum

Doubt about static S3 URLs

Unanswered
Californian posted this in #help-forum
Open in Discord
CalifornianOP
Hello folks,

In my app I make GET requests for some static images stored in an S3 bucket. I don't want to give public accesss to them. For POST requests, I know the existence of next-upload package (from @linesofcode ) but how to proceed for GET requests ? Should I use the AWS SDK in a server action to create a presigned URL and then display the image on the client using this presigned URL ? Or is there some quick wrapper to use out there ?

Thanks

59 Replies

getAsset function in next-upload will give you a presigned url
and yes presigned urls is the way to go
CalifornianOP
Nice, I didn't notice your package also solve this case. Thanks !
yep it's meant to handle file management end to end
i probably need to improve the description / add more documentation to explain this better
CalifornianOP
But does this suppose the file came to the S3 bucket from a next-upload POST request ? Does it cover the case where I had the file already there in the S3 bucket (added manually, for example) ?
If not, I need re-add them to the bucket via next-upload with an script, right ?
If you know the path then it should work
But yeah that’s what it assumes
But I’m pretty sure it can work without that assumption if you’re using paths
However I never tested that
if you're using ids then it needs to match the id in the storage adapter
CalifornianOP
Alright, I will see what I can do. Thanks
CalifornianOP
Hello @linesofcode , I implemented a Prisma store for next-upload but I'm having a weird bug .

I currently have a file /app/upload/nup.ts with the following content:

import { NextUpload } from 'next-upload';
import { NextUploadPrismaStore } from 'next-upload/store/prisma';

import { nextUploadConfig } from './config';
import { prisma } from '@/prisma/client';


export const nup = new NextUpload(
    nextUploadConfig,
    new NextUploadPrismaStore(prisma)
);


I also have a file /app/upload/route.ts with the following content:

import { NextRequest } from 'next/server';

import { nup } from './nup';

export const POST = (request: NextRequest) => nup.handler(request);

export const dynamic = 'force-dynamic';

// Optionally, if your application supports it you can run next-upload in the Edge runtime.
export const runtime = 'edge'; 


In a server action (implemented in the file /app/actions/test.ts), I'm calling it like:

'use server'

import { nup } from '@/app/upload/nup';

export async function testNextUploadPrismaStore() {
  console.log(nup.getStore());
}


Then I'm calling the server action in a client component. The console.log call displays undefined, as if I hadn't defined a store.

However, if I call the upload in the client component, like:

const nup = useNextUpload();

const handleUpload = async () => {
  const files = await getFiles();
  nup.upload(files);
}


Then everything works fine: the files are uploaded to the AWS S3 bucket and the data is injected in the database via the Prisma store.

Any idea on why the store is undefined in a server action ?
I am not sure
If you make a reproduction repo with this code
I can run it locally and debug
Is it undefined with other stores too?
If so maybe I can debug on my own without a reproduction
I’ll double check once I’m back home in an hour or two
CalifornianOP
If I add a line:

this.store = store as (NextUploadStore | undefined);


at the end of the NextUpload constructor, the problem is solved. But I still don't understand the reason.

I will check with other stores and tell you.
CalifornianOP
I just tested with KeyvStore and the problem is reproducible. The fix I mentioned above also works in this case. Apparently the NextUpload store variable is not loaded by the parent class (in the super call).
I can push the fix in my PR for the prisma store if you confirm it's indeed a bug.
But I want to write some unit tests for the prisma store before opening a PR. So far I am developing directly in my Next application with a symlink to the package.
Got it
I’ll look into it
And yeah definitely needs tests in the PR
And update the example app
To have a prisma example
It’s really straightforward, just adding another config and the rest should just work
At first glance the pr looks good 😊
CalifornianOP
Ok, I'll add some tests and update the example app
CalifornianOP
Hey @linesofcode , I added an example for Prisma store in the PR. I hope I will have some time tomorrow or Wednesday to write unit tests.

It is complicated to test because the Prisma client is not loaded at runtime. It is loaded inside the node_modules folder, from a schema file. When it is loaded, it affects the types in the store. What type could I use for the Prisma client instance inside the store ? I am using any for now to avoid all the hassle while testing.

Also, the tests needs to be idempotent. I am thinking in doing it with a script that:

1) Kills the containers for Postgres and minio and erase the docker volumes if there is some.
2) Unloads Prisma client with an empty schema.
3) Launch the containers for Postgres et minio.
4) Loads Prisma client from a schema file.
5) Launch tests.
6) Unloads Prisma client with an empty schema.
7) Kills the containers for Postgres and minio and erase the docker volumes.

What do you think ?
The killing of containers isn’t necessary. Just delete their contents using code, pretty sure how that’s how it works now
If you don’t know the types of prisma client ahead of time you could define your own subset of types ahead of time
Which match whatever the ultimate result of types is in prisma client
I’m not very familiar with prisma so maybe there’s other solutions
How are you planning on modularizing the next-upload related schema?
CalifornianOP
My idea is to let the Prisma schema to be defined by the client of the package (because the client will have a Prisma client already loaded in his node_modules folder anyway). In next-upload, the only dependency is @prisma/client (empty, I only need it for the types). I already tested that this works in my Next application. But it brings complications for the tests. Maybe the test could use a separate node_modules than the package to be able to deal with it ? What do you think ?
About the type, apparently Prisma doesn’t define a type for the client. So yeah, I will define my own, derived from any. Initially I was using PrismaClient for the type but this brings problems if the test uses the same node_modules than the package, because the test will load the PrismaClient
I will try to ask Prisma on GitHub about the type
@Californian For the undefined store issue, in your server action, be sure to call await nup.init() then the store will be defined. The way it works right now is that the store is lazily initialized when the route handler is hit. Since you're not using a route handler you'll need to initialize it yourself.

In a future release I will add better integration for server actions
No answer yet from me on the prisma stuff, I need some time to digest the prisma docs and understand how that integration should work
CalifornianOP
@linesofcode Thanks for the await nup.init() .
For the prisma integration, once you have a conclusion, let me know. I am open to help with this 🙂
CalifornianOP
@linesofcode Question about next-upload: once I call nup.upload(files) on client side, what is the best way to know the ids on server side later ? I'm currently doing a SQL query on the table next_upload_assets table trying to match the file name, the bucket name and the creation date (under a toleration delta) in the json column data . Is this the intended way to find these ids or I am missing something ?
You can provide an id
CalifornianOP
Where ? Is it in the nup.upload call in the client side ?
I see it accepts an array {file: File}[] as parameter
one sec
after you get a nup by calling the hook
This is what it accepts
so you can generate an id ahead of time and then pass that id to nup
and look up the data in your table using that id
does that work for you?
CalifornianOP
Ah, it's much simpler than I thought. This works, thanks !
Yep no problem