By default this addon will give every upload a unique key in your S3 bucket. If you would like to customize the key you can do so by configuring the API route.
// pages/api/s3-upload.js
import { APIRoute } from "next-s3-upload";
export default APIRoute.configure({
key(req, filename) {
return `my/uploads/path/${filename}`;
}
});
The key function can return a promise if you need to do something async.
// pages/api/s3-upload.js
import { APIRoute } from "next-s3-upload";
export default APIRoute.configure({
async key(req, filename) {
let path = await getPath();
return `${path}/${filename}`;
}
});
The AWS guidelines recommend using a specific subset of characters for key names. This library has a sanitizeKey()
function to remove any characters that could cause problems when stored on S3.
// pages/api/s3-upload.js
import { APIRoute, sanitizeKey } from "next-s3-upload";
export default APIRoute.configure({
key(req, filename) {
return `safe-file-name/${sanitizeKey(filename)}`;
}
});
This function is useful if you are accepting uploads for non-english filenames.
If you set up your IAM user to only upload specific file extensions then your key function must return a path ending with one of your allowed extensions.
If the key function returns a path that does not include an allowed extension then your upload will fail with an access denied error.
You can pass data from your React app to the key function using uploadToS3
options.
In the example below, we pass a projectId
from the frontend using the endpoint.request.body
option.
// Frontend component
function Component() {
let { uploadToS3 } = useS3Upload();
let handleSubmit = async () => {
// You can pass extra data using `endpoint.request.body`
await uploadToS3(file, {
endpoint: {
request: {
body: {
projectId: 123
}
}
}
});
};
}
Now the key function can read the passed projectId
from req.body.projectId
.
// pages/api/s3-upload.js
import { APIRoute } from "next-s3-upload";
export default APIRoute.configure({
async key(req, filename) {
let projectId = req.body.projectId; // 123
return `projects/${projectId}/${filename}`;
}
});
All data that needs to be passed from the frontend should be sent under the endpoint.request.body
object, since that data will get serialized into the request's body.
You can pass any data you'd like here, as long as it's serializable into JSON.
The uploadToS3
function can also add request headers that can be used by the key function.
// Frontend component
function Component() {
let { user } = useAuth();
let { uploadToS3 } = useS3Upload();
let handleSubmit = async () => {
let authToken = await user.getAuthToken();
await uploadToS3(file, {
endpoint: {
request: {
headers: {
authorization: authToken
}
}
}
});
};
}
And the authorization header can be read using req.headers.authorization
.
// pages/api/s3-upload.js
import { APIRoute } from "next-s3-upload";
export default APIRoute.configure({
async key(req, filename) {
let user = await getUserFromAuthToken(req.headers.authorization);
return `users/${user.id}/${filename}`;
}
});