Manuel
Manuel

Reputation: 9

Having problems uploading images to supabase storage using spring

I am trying to upload images to supabase storage using spring but every time I run the endpoint I get this error. I have only 1 bucket in storage called "slike" and it does not have any subfolders. I tried adding all available policies to that bucket but it just does not seem to work. I am using service_role key.

POST http://localhost:8080/posts/create

HTTP/1.1 500 
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 30 Dec 2024 00:36:22 GMT
Connection: close

{
  "timestamp": "2024-12-30T00:36:22.381+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "message": "Error uploading to Supabase: 400 Bad Request from PUT https://pccmxztqfmfucdbgcydr.supabase.co/storage/v1/object/slike/images.jpg",
  "path": "/posts/create"
}
Response file saved.
> 2024-12-30T013622.500.json

Response code: 500; Time: 24630ms (24 s 630 ms); Content length: 255 bytes (255 B)
@PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity<?> createPost(@RequestParam String userEmail,
                                        @RequestParam String textContent,
                                        @RequestPart(value = "file", required = false) MultipartFile file) {
        // 1. Get the user
        User user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new RuntimeException("User not found with email: " + userEmail));

        // 2. Only Partner can create a post
        if (user.getUserType() != UserType.PARTNER) {
            return ResponseEntity.badRequest().body("Only a Partner can create posts.");
        }

        // 3. If file is present, upload to Supabase
        String imageUrl = null;
        if (file != null && !file.isEmpty()) {
            // Build a unique path in the bucket:
            // e.g., "public/posts/" + System.currentTimeMillis() + "-" + file.getOriginalFilename()
            String pathInBucket = file.getOriginalFilename();
            imageUrl = supabaseStorageService.uploadFile(file, "slike", pathInBucket);
        }

        // 4. Create the Post in local DB (text + optional imageUrl)
        Post newPost = postService.createPost(user, textContent, imageUrl);

        // 5. Return the newly created Post
        return ResponseEntity.ok(newPost);
    }
package hr.fer.sportconnect.db;

import hr.fer.sportconnect.db.SupabaseStorageService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.WebClient;

@Service
public class SupabaseStorageServiceImpl implements SupabaseStorageService {

    // These come from application.properties or environment variables
    @Value("${supabase.project.url}")  // e.g. "https://xxxxxx.supabase.co"
    private String supabaseUrl;

    @Value("${supabase.key}") // Your service_role or anon key
    private String supabaseKey;

    @Override
    public String uploadFile(MultipartFile file, String bucketName, String pathInBucket) {
        try {
            // 1. Convert to byte[]
            byte[] fileBytes = file.getBytes();

            // 2. Build the full upload endpoint:
            //    "https://<project>.supabase.co/storage/v1/object/{bucketName}/{pathInBucket}"
            String uploadUrl = supabaseUrl + "/storage/v1/object/"
                    + bucketName + "/" + pathInBucket;

            // 3. Perform POST or PUT request
            WebClient webClient = WebClient.builder()
                    .baseUrl(uploadUrl)
                    .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + supabaseKey)
                    .build();

            webClient.put()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .bodyValue(fileBytes)
                    .retrieve()
                    .bodyToMono(String.class) // The response body
                    .block(); // Execute synchronously

            // 4. Build the public URL (assuming your bucket is public):
            //    e.g., "https://xxxxxx.supabase.co/storage/v1/object/public/{bucketName}/{pathInBucket}"
            // If it's private, you'd generate a signed URL separately.
            String publicUrl = supabaseUrl + "/storage/v1/object/public/"
                    + bucketName + "/" + pathInBucket;


            return publicUrl;

        } catch (Exception e) {
            throw new RuntimeException("Error uploading to Supabase: " + e.getMessage(), e);
        }
    }
}

Upvotes: 0

Views: 72

Answers (0)

Related Questions