Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to display images or upload user image updates #3

Open
erwaf444 opened this issue Mar 23, 2024 · 2 comments
Open

Unable to display images or upload user image updates #3

erwaf444 opened this issue Mar 23, 2024 · 2 comments

Comments

@erwaf444
Copy link

erwaf444 commented Mar 23, 2024

I encountered some problems, regarding the inability to display images normally on the All Files page, and when clicking download, {"code":"InvalidStoragePath","message":"Invalid storage path: "xxxxxxx" is not a valid UUID string."},
When updating user image, check the convex log and it will show
failure.
Mutation
users:updateUser

Maybe the problem lies in the url or the tokenIdentifier?

this is my code

case "user.created":
          await ctx.runMutation(internal.users.createUser, {
            tokenIdentifier: `https://${process.env.CLERK_HOSTNAME}|${result.data.id}`,
            name: `
              ${result.data.first_name ?? ""} 
              ${result.data.last_name ?? ""}
            `,
            image: result.data.image_url,
          });
          break;
        case "user.updated":
          await ctx.runMutation(internal.users.updateUser, {
            tokenIdentifier: `https://${process.env.CLERK_HOSTNAME}|${result.data.id}`,
            name: `
              ${result.data.first_name ?? ""} 
              ${result.data.last_name ?? ""}
            `,
            image: result.data.image_url,
          });
          break;
        case 'organizationMembership.created':
            await ctx.runMutation(internal.users.addOrgIdToUser, {
                tokenIdentifier: `https://${process.env.CLERK_HOSTNAME}|${result.data.public_user_data.user_id}`,
                orgId: result.data.organization.id,
                role: result.data.role === 'org:admin' ? "admin" : "member",
            });
            break;
          case 'organizationMembership.updated':
            await ctx.runMutation(internal.users.updateRoleInOrgForUser, {
                tokenIdentifier: `https://${process.env.CLERK_HOSTNAME}|${result.data.public_user_data.user_id}`,
                orgId: result.data.organization.id,
                role: result.data.role === 'org:admin' ? "admin" : "member",
            });
            break;
export const createUser = internalMutation({
    args: { tokenIdentifier: v.string(), name: v.string(),  image: v.string() },
    async handler(ctx, args) {
        await ctx.db.insert("users", {
            tokenIdentifier: args.tokenIdentifier,
            orgIds: [],
            name: args.name,
            image: args.image
        })
    }
})

export const updateUser = internalMutation({
    args: { tokenIdentifier: v.string(), name: v.string(),  image: v.string() },
    async handler(ctx, args) {
        const user = await ctx.db
            .query("users")
            .withIndex("by_tokenIdentifier", (q) => 
                q.eq("tokenIdentifier", args.tokenIdentifier)
                ).first();

        if (!user) {
            throw new ConvexError("User not found");
        }

        await ctx.db.patch(user._id, {
            name: args.name,
            image: args.image
        })
    }
})
@dushyanth31
Copy link

dushyanth31 commented Mar 27, 2024

It's already solved:

Step 1: Setting Up Your Convex Function to Store File URLs
When you upload a file using Convex, ensure you store not just the file metadata but also the URL to access the file. This is done in your mutation function when creating a file entry in your database.

// convex/files.ts

export const createFile = mutation({
args: {
name: v.string(),
fileId: v.id("_storage"),
orgId: v.string(),
type: fileTypes,
},
async handler(ctx, args) {
const hasAccess = await hasAccessToOrg(ctx, args.orgId);

if (!hasAccess) {
  throw new ConvexError("you do not have access to this org");
}

const fileUrl = await ctx.storage.getUrl(args.fileId);
    
if (!fileUrl) {
  throw new ConvexError("file not found");
}

await ctx.db.insert("files", {
  name: args.name,
  orgId: args.orgId,
  fileId: args.fileId,
  type: args.type,
  userId: hasAccess.user._id,
  url: fileUrl,
});
},
});

Step 2: Add to your schema

export default defineSchema({
  files: defineTable({ 
    name: v.string(),
    type: fileTypes,
    orgId: v.string(),
    fileId: v.id('_storage'),
    userId: v.id('users'),
    shouldDelete: v.optional(v.boolean()),
    url: v.string(),
   })

Step 3: Apply the changes to this file:

//src/app/dashboard/_components/file-card.tsx

{file.type === "image" && ( <Image alt={file.name} width="200" height="100" src={file.url} /> )}

Step 4: you'll display each file with a download button. When the button is clicked, the file URL stored in your database is used to initiate the download.

//_components/file-actions.tsx

 Just replace this with existing one or just add the changes,
<DropdownMenu>
        <DropdownMenuTrigger>
          <MoreVertical />
        </DropdownMenuTrigger>
        <DropdownMenuContent>
          <DropdownMenuItem
            onClick={() => {
              window.open(file.url, "_blank");
            }}
            className="flex gap-1 items-center cursor-pointer"
          >
            <FileIcon className="w-4 h-4" /> Download
          </DropdownMenuItem>

Hope it helps. Thank you.

@thuongtruong1009
Copy link

It's already solved:

Step 1: Setting Up Your Convex Function to Store File URLs When you upload a file using Convex, ensure you store not just the file metadata but also the URL to access the file. This is done in your mutation function when creating a file entry in your database.

// convex/files.ts

export const createFile = mutation({
args: {
name: v.string(),
fileId: v.id("_storage"),
orgId: v.string(),
type: fileTypes,
},
async handler(ctx, args) {
const hasAccess = await hasAccessToOrg(ctx, args.orgId);

if (!hasAccess) {
  throw new ConvexError("you do not have access to this org");
}

const fileUrl = await ctx.storage.getUrl(args.fileId);
    
if (!fileUrl) {
  throw new ConvexError("file not found");
}

await ctx.db.insert("files", {
  name: args.name,
  orgId: args.orgId,
  fileId: args.fileId,
  type: args.type,
  userId: hasAccess.user._id,
  url: fileUrl,
});
},
});

Step 2: Add to your schema

export default defineSchema({
  files: defineTable({ 
    name: v.string(),
    type: fileTypes,
    orgId: v.string(),
    fileId: v.id('_storage'),
    userId: v.id('users'),
    shouldDelete: v.optional(v.boolean()),
    url: v.string(),
   })

Step 3: Apply the changes to this file:

//src/app/dashboard/_components/file-card.tsx

{file.type === "image" && ( <Image alt={file.name} width="200" height="100" src={file.url} /> )}

Step 4: you'll display each file with a download button. When the button is clicked, the file URL stored in your database is used to initiate the download.

//_components/file-actions.tsx

 Just replace this with existing one or just add the changes,
<DropdownMenu>
        <DropdownMenuTrigger>
          <MoreVertical />
        </DropdownMenuTrigger>
        <DropdownMenuContent>
          <DropdownMenuItem
            onClick={() => {
              window.open(file.url, "_blank");
            }}
            className="flex gap-1 items-center cursor-pointer"
          >
            <FileIcon className="w-4 h-4" /> Download
          </DropdownMenuItem>

Hope it helps. Thank you.

i get error type check:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants