2

I’ve run into a weird issue with Supabase Storage and could really use some help. I'm building a document uploader using Supabase Storage. Everything works perfectly on desktop, but when I try uploading from mobile browsers, the upload just loads forever. I've tried using different networks, browsers and devices, but it's still the same problem. The function below handles file upload.

const handleSubmit = useCallback(async (e: React.FormEvent) => {
    e.preventDefault()

    if (!file) {
      setError("Please select a file to upload.")
      return
    }
    if (!user) {
      setError("User not authenticated. Please log in.")
      router.push("/login") 
      return
    }
    if (!form.title || !form.course_code || !form.course_title || !form.level || !form.semester || !form.document_type) {
      setError("Please fill in all required fields.")
      return
    }

    // Validate file again before upload
    const validationError = validateFile(file)
    if (validationError) {
      setError(validationError)
      return
    }

    setLoading(true)
    setError("")
    setSuccess("")
    setRetryCount(0)
    setIsRetrying(false)

    try {      
      const fileHash = await calculateFileHash(file)

      const { data, error } = await supabase
      .from("documents")
      .select("id")
      .eq("file_hash", fileHash)
      .limit(1)

      if (error) throw error
      if (data && data.length > 0) {
        setError("This file (or an identical version) has already been uploaded.")
        return
      }
      
      const uniqueFileName = `${Date.now()}-${file.name.replace(/[^a-zA-Z0-9.]/g, '_')}`
      const filePath = `${user.id}/${uniqueFileName} `

      const { error: uploadError } = await supabase.storage.from("documents").upload(filePath, file)
      if (uploadError) {
        if (uploadError.message.includes("duplicate key")) {
          setError("A file with this name already exists in your storage. Please rename your file or try again.")
        } else {
          throw uploadError
        }
        return
      }

      const { error: dbError } = await supabase.from("documents").insert({
        title: form.title,
        description: form.description || null,
        file_name: file.name,
        file_size: file.size,
        file_type: file.type || "application/octet-stream",
        file_hash: fileHash,
        course_code: form.course_code,
        course_title: form.course_title,
        level: form.level,
        semester: form.semester,
        document_type: form.document_type,
        is_public: form.is_public,
        uploader_id: user.id,
        uploader_role: user.role,
        storage_path: filePath,
        created_at: new Date().toISOString(),
      })

      if (dbError) {
        console.error("Database insert error:", dbError)
        throw new Error(`Failed to save document metadata: ${dbError.message}`)
      }

      setSuccess("Document uploaded successfully! 🎉 Redirecting to documents...")
      
      setFile(null)
      setForm({
        title: "",
        description: "",
        course_code: "",
        course_title: "",
        level: "",
        semester: "",
        document_type: "",
        is_public: true,
      })

      setTimeout(() => {
        router.push("/dashboard")
      }, 2000)
    } catch (err: any) {
      console.error("Upload process error:", err)
      setError(err.message || "An unexpected error occurred during upload.")
    } finally {
      setLoading(false)
    }
  }, [file, user, form, router, validateFile])

I've tried looking at some supabase settings but there's nothing to change there.

1 Answer 1

0

I was wondering if you solved this problem! I recently ran into the exact same issue and found a solution, in case you haven't fixed it yet...
(note: I'm building a website using Nuxt 3 and Supabase.)

My solution was to create a dedicated API route (or endpoint) and move the core logic (file uploads, inserting records to Supabase, etc.) there, and then send the request to that API route.

I also encountered a very weird bug where the session would be lost only on Android. To handle this, when sending the request to the API route, I explicitly added the access token like Authorization: Bearer {access_token}. Inside the API route, I then extracted the token from the header to re-initialize the Supabase client. This finally resolved the issue! Hope this helps you as well🤞

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.