enzostvs HF Staff commited on
Commit
c644c2c
·
1 Parent(s): ecb9cd6

fix download

Browse files
app/api/me/projects/[namespace]/[repoId]/download/route.ts CHANGED
@@ -49,21 +49,18 @@ export async function GET(
49
  name: `${namespace}/${repoId}`,
50
  };
51
 
52
- // Create a new JSZip instance
53
  const zip = new JSZip();
54
 
55
- // Iterate through all files in the repo
56
  for await (const fileInfo of listFiles({
57
  repo,
58
- accessToken: user.token as string
 
59
  })) {
60
- // Skip directories and hidden files
61
  if (fileInfo.type === "directory" || fileInfo.path.startsWith(".")) {
62
  continue;
63
  }
64
 
65
  try {
66
- // Download the file
67
  const blob = await downloadFile({
68
  repo,
69
  accessToken: user.token as string,
@@ -72,17 +69,14 @@ export async function GET(
72
  });
73
 
74
  if (blob) {
75
- // Add file to zip
76
  const arrayBuffer = await blob.arrayBuffer();
77
  zip.file(fileInfo.path, arrayBuffer);
78
  }
79
  } catch (error) {
80
  console.error(`Error downloading file ${fileInfo.path}:`, error);
81
- // Continue with other files even if one fails
82
  }
83
  }
84
 
85
- // Generate the ZIP file as a Blob
86
  const zipBlob = await zip.generateAsync({
87
  type: "blob",
88
  compression: "DEFLATE",
@@ -91,11 +85,9 @@ export async function GET(
91
  }
92
  });
93
 
94
- // Create the filename from the project name
95
  const projectName = `${namespace}-${repoId}`.replace(/[^a-zA-Z0-9-_]/g, '_');
96
  const filename = `${projectName}.zip`;
97
 
98
- // Return the ZIP file
99
  return new NextResponse(zipBlob, {
100
  headers: {
101
  "Content-Type": "application/zip",
@@ -104,7 +96,6 @@ export async function GET(
104
  },
105
  });
106
  } catch (error: any) {
107
- console.error("Error creating ZIP:", error);
108
  return NextResponse.json(
109
  { ok: false, error: error.message || "Failed to create ZIP file" },
110
  { status: 500 }
 
49
  name: `${namespace}/${repoId}`,
50
  };
51
 
 
52
  const zip = new JSZip();
53
 
 
54
  for await (const fileInfo of listFiles({
55
  repo,
56
+ accessToken: user.token as string,
57
+ recursive: true,
58
  })) {
 
59
  if (fileInfo.type === "directory" || fileInfo.path.startsWith(".")) {
60
  continue;
61
  }
62
 
63
  try {
 
64
  const blob = await downloadFile({
65
  repo,
66
  accessToken: user.token as string,
 
69
  });
70
 
71
  if (blob) {
 
72
  const arrayBuffer = await blob.arrayBuffer();
73
  zip.file(fileInfo.path, arrayBuffer);
74
  }
75
  } catch (error) {
76
  console.error(`Error downloading file ${fileInfo.path}:`, error);
 
77
  }
78
  }
79
 
 
80
  const zipBlob = await zip.generateAsync({
81
  type: "blob",
82
  compression: "DEFLATE",
 
85
  }
86
  });
87
 
 
88
  const projectName = `${namespace}-${repoId}`.replace(/[^a-zA-Z0-9-_]/g, '_');
89
  const filename = `${projectName}.zip`;
90
 
 
91
  return new NextResponse(zipBlob, {
92
  headers: {
93
  "Content-Type": "application/zip",
 
96
  },
97
  });
98
  } catch (error: any) {
 
99
  return NextResponse.json(
100
  { ok: false, error: error.message || "Failed to create ZIP file" },
101
  { status: 500 }
components/my-projects/project-card.tsx CHANGED
@@ -17,6 +17,7 @@ import {
17
  DropdownMenuTrigger,
18
  } from "@/components/ui/dropdown-menu";
19
  import { ProjectType } from "@/types";
 
20
 
21
  // from-red-500 to-red-500
22
  // from-yellow-500 to-yellow-500
@@ -44,8 +45,49 @@ export function ProjectCard({
44
  }
45
  };
46
 
47
- const handleDownload = () => {
48
- window.open(`/deepsite/api/me/projects/${project.name}/download`, "_blank");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  };
50
  // from-gray-600 to-gray-600
51
  // from-blue-600 to-blue-600
 
17
  DropdownMenuTrigger,
18
  } from "@/components/ui/dropdown-menu";
19
  import { ProjectType } from "@/types";
20
+ import { toast } from "sonner";
21
 
22
  // from-red-500 to-red-500
23
  // from-yellow-500 to-yellow-500
 
45
  }
46
  };
47
 
48
+ const handleDownload = async () => {
49
+ try {
50
+ toast.info("Preparing download...");
51
+
52
+ // Fetch with credentials to ensure cookies are sent
53
+ const response = await fetch(
54
+ `/deepsite/api/me/projects/${project.name}/download`,
55
+ {
56
+ credentials: "include",
57
+ headers: {
58
+ Accept: "application/zip",
59
+ },
60
+ }
61
+ );
62
+
63
+ if (!response.ok) {
64
+ const error = await response
65
+ .json()
66
+ .catch(() => ({ error: "Download failed" }));
67
+ toast.error(error.error || "Failed to download project");
68
+ return;
69
+ }
70
+
71
+ // Create blob from response
72
+ const blob = await response.blob();
73
+
74
+ // Create download link
75
+ const url = window.URL.createObjectURL(blob);
76
+ const link = document.createElement("a");
77
+ link.href = url;
78
+ link.download = `${project.name.replace(/\//g, "-")}.zip`;
79
+ document.body.appendChild(link);
80
+ link.click();
81
+
82
+ // Cleanup
83
+ document.body.removeChild(link);
84
+ window.URL.revokeObjectURL(url);
85
+
86
+ toast.success("Download started!");
87
+ } catch (error) {
88
+ console.error("Download error:", error);
89
+ toast.error("Failed to download project");
90
+ }
91
  };
92
  // from-gray-600 to-gray-600
93
  // from-blue-600 to-blue-600