next-s3-upload
next-s3-upload copied to clipboard
Custom Path for File Uploads with App Router
I am encountering difficulties specifying a custom path for file uploads when using the 'next-s3-upload' library within a Next.js application, specifically with the App Router. The library provides an example for configuring the API route with a custom key function, but it seems that this configuration may not be fully compatible with the App Router.
Documentation Reference: The relevant documentation snippet is as follows:
// pages/api/s3-upload.js
import { APIRoute } from "next-s3-upload";
export default APIRoute.configure({
key(req, filename) {
return `my/uploads/path/${filename}`;
}
});
Issue Details:
Expected Behavior: I expect to be able to specify a custom path for file uploads using the library when using the App Router. Actual Behavior: When using the provided configuration with App Router, I encounter errors such as 'TypeError: Body is unusable' or 'TypeError: s.status is not a function'.
Additional Information:
The configuration appears to be designed for the Pages Router, and it may not work seamlessly with the App Router in Next.js. It seems that there might be a need for additional documentation or clarification on how to configure the library for the App Router in Next.js.
Update
By using the POST
export from "next-s3-upload/route" instead of APIRoute
, I was able to specify a custom path for file uploads within the App Router.
import { POST as route } from "next-s3-upload/route";
export const POST = route.configure({
async key(req, filename) {
console.log('KEY CHANGED');
return `${'myfiles'}/${filename}`;
},
});
However, upon further testing, I encountered difficulties accessing the body of the req
object when attempting to dynamically set the file path for uploads. The attempt to use await req.json()
resulted in the error: TypeError: Body is unusable
.
import { POST as route } from "next-s3-upload/route";
export const POST = route.configure({
async key(req, filename) {
try {
const body = await req.json();
const folderName = body.folderName;
return `${folderName}/${filename}`;
} catch (error) {
console.error("Error parsing JSON body:", error);
return `${filename}`;
}
},
});
Additionally, attempting to access the body directly using req.body
returned: "ReadableStream { locked: true, state: 'closed', supportsBYOB: false }"
.
This further complicates the process of dynamically setting the file path.
I had the same issue. The request object is not usable in this context. To get around this, the client side posts the folder location in the header instead of the body.
const location = req.headers.get('location')
It now works as expected.
I cant seem to get body or headers to work but what i did to simplify things is use the url
let handleFileChange = async (event) => {
let file = event.target.files[0];
let { url } = await uploadToS3(file, {
endpoint: {
request: {
url: `/api/s3-upload/?folder=works`
}
}
});
setImageUrl(url);
};
import { sanitizeKey } from "next-s3-upload";
import { POST as route } from "next-s3-upload/route";
export const POST = route.configure({
async key(req, filename) {
try {
const url = req.url.split('?')[1];
const params = new URLSearchParams(url);
const folder = params.get('folder');
return `${folder}/${sanitizeKey(filename)}`;
} catch (error) {
console.error("Error parsing JSON body:", error);
return `${filename}`;
}
},
});