implement down load file
This commit is contained in:
parent
fe9eb915e1
commit
1abeab6e46
5 changed files with 119 additions and 7 deletions
|
|
@ -355,4 +355,18 @@ Now we will go now and add metadata
|
|||
|
||||
Now we have the metadata along with some great filters on the data board page
|
||||
|
||||
Now we are going to implement an an update of a file or folder stored. 12/1/2026
|
||||
Now we are going to implement an an update of a file or folder stored. 12/1/2026
|
||||
|
||||
For download there 2 function we need to implement
|
||||
|
||||
1) down load the file to ~/user/Downloads, this should work for any file type including pdf
|
||||
|
||||
2) if the file is a pdf open the file in another tab in the browser as most browser support reading a pdf
|
||||
|
||||
For download there 2 function we need to implement
|
||||
|
||||
1) down load the file to ~/user/Downloads, this should work for any file type including pdf
|
||||
|
||||
2) if the file is a pdf open the file in another tab in the browser as most browser support reading a pdf
|
||||
|
||||
So we need to implement 2 new actions, downLoad file and open pdf to read. Does this make sense ?
|
||||
BIN
docs/notes.pdf
BIN
docs/notes.pdf
Binary file not shown.
66
src/app/api/download/route.ts
Normal file
66
src/app/api/download/route.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// src/app/api/download/route.ts
|
||||
"use server"
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { auth } from "@/auth"; // Import the auth function from your central config
|
||||
import { prisma } from '@/lib/prisma';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
// 1. Check Authentication using the V5 auth() helper
|
||||
const session = await auth();
|
||||
|
||||
// In V5, tokens are usually handled in the session callback
|
||||
if (!session || !session.accessToken) {
|
||||
return new NextResponse("Unauthorized - No Access Token found", { status: 401 });
|
||||
}
|
||||
|
||||
// 2. Get parameters from URL
|
||||
const { searchParams } = new URL(request.url);
|
||||
const fileNodeId = searchParams.get('id');
|
||||
const mode = searchParams.get('mode') === 'inline' ? 'inline' : 'attachment';
|
||||
|
||||
if (!fileNodeId) {
|
||||
return new NextResponse("File ID is required", { status: 400 });
|
||||
}
|
||||
|
||||
// 3. Find the file in your Postgres FileNode table
|
||||
const fileNode = await prisma.fileNode.findUnique({
|
||||
where: { id: fileNodeId }
|
||||
});
|
||||
|
||||
if (!fileNode || !fileNode.oneDriveId) {
|
||||
return new NextResponse("File not found in database", { status: 404 });
|
||||
}
|
||||
|
||||
// 4. Fetch the file stream from Microsoft Graph
|
||||
const graphResponse = await fetch(
|
||||
`https://graph.microsoft.com/v1.0/me/drive/items/${fileNode.oneDriveId}/content`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${session.accessToken}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!graphResponse.ok) {
|
||||
const errorText = await graphResponse.text();
|
||||
console.error('MS Graph Error:', errorText);
|
||||
return new NextResponse(`OneDrive Error: ${graphResponse.statusText}`, { status: graphResponse.status });
|
||||
}
|
||||
|
||||
// 5. Stream the response directly to the client
|
||||
return new NextResponse(graphResponse.body, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': fileNode.mimeType || 'application/octet-stream',
|
||||
// Note: Using encodeURIComponent for filename to handle special characters
|
||||
'Content-Disposition': `${mode}; filename="${encodeURIComponent(fileNode.name)}"`,
|
||||
},
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Download error:', error);
|
||||
return new NextResponse("Internal Server Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
20
src/auth.ts
20
src/auth.ts
|
|
@ -1,3 +1,4 @@
|
|||
// src/auth.ts
|
||||
import NextAuth from "next-auth";
|
||||
import { PrismaAdapter } from "@auth/prisma-adapter";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
|
@ -10,6 +11,7 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
|||
callbacks: {
|
||||
async jwt({ token, account, user }) {
|
||||
// 1. Handle OAuth tokens (from first sign-in)
|
||||
// This captures the tokens directly from the Microsoft Azure response
|
||||
if (account) {
|
||||
token.accessToken = account.access_token;
|
||||
token.refreshToken = account.refresh_token;
|
||||
|
|
@ -17,10 +19,10 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
|||
}
|
||||
|
||||
// 2. Attach User ID and Role to the token
|
||||
// When 'user' exists, it's the first time we've fetched this user from the DB during login
|
||||
// This runs when the user first logs in
|
||||
if (user) {
|
||||
token.sub = user.id;
|
||||
// @ts-ignore - 'role' exists on our custom User model
|
||||
// @ts-ignore - 'role' is a custom field in your Postgres User table
|
||||
token.role = user.role;
|
||||
}
|
||||
|
||||
|
|
@ -29,10 +31,16 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
|||
|
||||
async session({ session, token }) {
|
||||
// 3. Pass values from the JWT Token into the Client-facing Session
|
||||
if (session?.user && token.sub) {
|
||||
session.user.id = token.sub;
|
||||
// @ts-ignore - Attaching the role so the Navbar and Settings page can see it
|
||||
session.user.role = token.role;
|
||||
// This makes the tokens and IDs available to your API routes and Components
|
||||
if (session?.user) {
|
||||
session.user.id = token.sub as string;
|
||||
|
||||
// @ts-ignore - Attaching the role for UI permissions
|
||||
session.user.role = token.role as string;
|
||||
|
||||
// IMPORTANT: We must attach the accessToken here so the
|
||||
// /api/download route can use it to fetch from MS Graph
|
||||
session.accessToken = token.accessToken as string;
|
||||
}
|
||||
return session;
|
||||
},
|
||||
|
|
|
|||
24
src/types/next-auth.d.ts
vendored
Normal file
24
src/types/next-auth.d.ts
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// src/types/next-auth.d.ts
|
||||
import NextAuth, { DefaultSession } from "next-auth"
|
||||
import { JWT } from "next-auth/jwt"
|
||||
|
||||
declare module "next-auth" {
|
||||
/**
|
||||
* Returned by `useSession`, `auth`, and received as a prop on the `SessionProvider` React Context
|
||||
*/
|
||||
interface Session {
|
||||
accessToken?: string;
|
||||
user: {
|
||||
id: string;
|
||||
role?: string;
|
||||
} & DefaultSession["user"]
|
||||
}
|
||||
}
|
||||
|
||||
declare module "next-auth/jwt" {
|
||||
/** Returned by the `jwt` callback and `getToken`, when using JWT sessions */
|
||||
interface JWT {
|
||||
accessToken?: string;
|
||||
role?: string;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue