I am getting errors with uploadthing and NextJS. The upload functionality worked before the version 14 and now doesn’t. I tried reverting to the previous version of NextJS 13 and now I’m getting console errors (Windows VSCode Terminal).
PS C:UsersHPDesktopDevelopmentKind Courseskind-courses> npm i
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: [email protected]
npm WARN Found: [email protected]
npm WARN node_modules/next
npm WARN next@"^13.4.12" from the root project
npm WARN 2 more (@clerk/nextjs, @uploadthing/react)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peerOptional next@"14.0.1" from @uploadthing/[email protected]
npm WARN node_modules/@uploadthing/react
npm WARN @uploadthing/react@"^6.0.1" from the root project
npm ERR! code ECONNRESET
npm ERR! errno ECONNRESET
npm ERR! network Invalid response body while trying to fetch https://registry.npmjs.org/@next%2fenv: aborted
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly. See: 'npm help config'
npm ERR! A complete log of this run can be found in: C:UsersHPAppDataLocalnpm-cache_logs2023-11-25T23_37_06_402Z-debug-0.log
At this point I wanted to try something else, like the native file upload but as a complete beginner on Nextjs and React and TypeScript, I have no clue where to start. I followed the whole documentation and did things right (I know this because the functionality worked). I also noticed that uploadthing gets UPDATED almost everyday and I think that’s why the functionality is working.
In my app/api/uploadthing/core.ts
import { createUploadthing, type FileRouter } from "uploadthing/next";
const f = createUploadthing();
const auth = (req: Request) => ({ id: "fakeId" }); // Fake auth function
// FileRouter for your app, can contain multiple FileRoutes
export const ourFileRouter = {
// Define as many FileRoutes as you like, each with a unique routeSlug
imageUploader: f({ image: { maxFileSize: "4MB" } })
// Set permissions and file types for this FileRoute
.middleware(async ({ req }) => {
// This code runs on your server before upload
const user = await auth(req);
// If you throw, the user will not be able to upload
if (!user) throw new Error("Unauthorized");
// Whatever is returned here is accessible in onUploadComplete as `metadata`
return { userId: user.id };
})
.onUploadComplete(async ({ metadata, file }) => {
// This code RUNS ON YOUR SERVER after upload
console.log("Upload complete for userId:", metadata.userId);
console.log("file url", file.url);
// !!! Whatever is returned here is sent to the clientside `onClientUploadComplete` callback
return { uploadedBy: metadata.userId };
}),
} satisfies FileRouter;
export type OurFileRouter = typeof ourFileRouter;
app/api/uploadthing/route.ts
import { createNextRouteHandler } from "uploadthing/next";
import { ourFileRouter } from "./core";
// Export routes for Next App Router
export const { GET, POST } = createNextRouteHandler({
router: ourFileRouter,
});
tailwind.config.ts
import { withUt } from "uploadthing/tw";
export default withUt({
// Your existing Tailwind config
content: ["./src/**/*.{ts,tsx,mdx}"],
...
});
app/(dashboard)/(routes)/teacher/courses/[courseId]/_components/image-form.tsx
"use client"
import * as z from "zod";
import axios from "axios";
import { ImageIcon, Pencil, PlusCircle } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";
import { useRouter } from "next/navigation";
import Image from 'next/image'
import { Button } from "@/components/ui/button";
import { Class } from "@prisma/client";
import { FileUpload } from "@/components/file-upload";
interface ImageFormProps {
initialData: Class;
courseId: string;//or class
};
const formShema = z.object({
imageUrl: z.string().min(1, ({
message: "Image is required",
}))
})
export const ImageForm = ({
initialData,
courseId,
}: ImageFormProps) => {
const [isEditing, setIsEditing] = useState(false);
const toggleEdit = () => {
setIsEditing((current) => !current);
}
const router = useRouter();
const onSubmit = async (values: z.infer<typeof formShema>) => {
console.log("Form Values:", values);
try {
await axios.patch(`/api/courses/${courseId}`, values);
toast.success("Class Updated");
toggleEdit();
router.refresh();
} catch {
toast.error("Something went wrong");
}
}
return(
<div className="mt-6 border bg-slate-100 rounded-md p-4">
<div className="font-medium flex items-center justify-between">
Class Image
<Button onClick={toggleEdit} variant="ghost">
{ isEditing && (
<>Cancel</>
)}
{!isEditing && !initialData.imageUrl && (
<>
<PlusCircle className="h-4 w-4 mr-2" />
Add Image
</>
)}
{
!isEditing && initialData.imageUrl && (
<>
<Pencil className="h-4 w-4 mr-2 "/>
Edit Image
</>
)
}
</Button>
</div>
{!isEditing && (
!initialData.imageUrl ? (
<div className="flex items-center justify-center h-60 bg-slate-200 rounded-md">
<ImageIcon className="h-10 w-10 text-slate-500"/>
</div>
) : (
<div className="relative aspect-video mt-2">
<Image alt="Upload" fill className="object-cover rounded-md" src={initialData.imageUrl }/>
</div>
)
)}
{isEditing && (
<div>
<FileUpload
endpoint="courseImage"//or classImage
onChange={(url) => {
if(url){
onSubmit({ imageUrl: url})
}
}}
/>
<div className="text-xs text-muted-foreground mt-4">
16:9 aspect ratio recomended
</div>
</div>
)}
</div>
)
}
And I’m also encountering this when I run the app and try to upload a file.
✓ Compiled /api/uploadthing/route in 1218ms (899 modules)
○ Compiling /not-found ...
✓ Compiled /not-found in 3.8s (1468 modules)
[UT] UploadThing dev server is now running!
[UT] UploadThing dev server is now running!
[UT] SIMULATING FILE UPLOAD WEBHOOK CALLBACK http://localhost:3000/api/uploadthing?slug=courseImage
INFO: Clerk: The request to /api/uploadthing is being protected (401) because there is no signed-in user, and the path is included in `apiRoutes`. To
prevent this behavior, choose one of:
1. To prevent Clerk authentication from protecting (401) the api route, remove the rule matching "/api/uploadthing" from the `apiRoutes` array passed
to authMiddleware
2. To make the route accessible to both signed in and signed out users, pass `publicRoutes: ["/api/uploadthing"]` to authMiddleware
3. To prevent Clerk authentication from running at all, pass `ignoredRoutes: ["/((?!api|trpc))(_next.*|.+.[w]+$)", "/api/uploadthing"]` to authMiddleware
4. Pass a custom `afterAuth` to authMiddleware, and replace Clerk's default behavior of redirecting unless a route is included in publicRoutes
For additional information about middleware, please visit https://clerk.com/docs/nextjs/middleware
(This log only appears in development mode, or if `debug: true` is passed to authMiddleware)
[UT] Failed to simulate callback for file. Is your webhook configured correctly? 93f6b985-5279-4803-992c-416dcf7614f9-6s0ujg.png
2
Answers
The 6.0.3 Uploadthing version resolve the error for me. She’s released 4 days ago.
you can bypass this by making your route public in authMiddleware() , go to ur root directory if u are using app then seach for middleware.ts