Issue
I am trying to store an image to Google cloud storage from my REST endpoint. But when i see the image on Google Cloud storage it shows an empty image.
My Service class
package com.example.firebase.springbootfirebasedemo.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.example.firebase.springbootfirebasedemo.entity.Review;
import com.google.api.core.ApiFuture;
import com.google.cloud.firestore.DocumentReference;
import com.google.cloud.firestore.DocumentSnapshot;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.WriteResult;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.firebase.cloud.FirestoreClient;
@Service
public class ReviewService {
@Autowired
private Storage storage;
private static final String COLLECTION_NAME ="Reviews";
private static final String BUCKET_NAME = "gcpfirebase";
public String saveReview(Review review, MultipartFile file) throws ExecutionException, InterruptedException, IOException {
File convFile = new File( file.getOriginalFilename() );
FileOutputStream fos = new FileOutputStream( convFile );
fos.write( file.getBytes());
fos.close();
BlobInfo blobInfo = storage.create(BlobInfo.newBuilder(BUCKET_NAME, file.getOriginalFilename()).build());
System.out.println(blobInfo.getMediaLink());
// .build()
// file.openStream()
Firestore dbFirestore= FirestoreClient.getFirestore();
ApiFuture<WriteResult> collectionApiFuture=dbFirestore.collection(COLLECTION_NAME).document(review.getName()).set(review);
return collectionApiFuture.get().getUpdateTime().toString();
}
public Review getReviewDetailsByname(String name) throws ExecutionException, InterruptedException {
Firestore dbFirestore= FirestoreClient.getFirestore();
DocumentReference documentReference=dbFirestore.collection(COLLECTION_NAME).document(name);
ApiFuture<DocumentSnapshot> future=documentReference.get();
DocumentSnapshot document=future.get();
Review review=null;
if(document.exists()) {
review = document.toObject(Review.class);
return review;
}else{
return null;
}
}
public List<Review> getAllReviews() throws ExecutionException, InterruptedException {
Firestore dbFirestore= FirestoreClient.getFirestore();
Iterable<DocumentReference> documentReference=dbFirestore.collection(COLLECTION_NAME).listDocuments();
Iterator<DocumentReference> iterator=documentReference.iterator();
List<Review> reviewList=new ArrayList<>();
Review review=null;
while(iterator.hasNext()){
DocumentReference documentReference1=iterator.next();
ApiFuture<DocumentSnapshot> future= documentReference1.get();
DocumentSnapshot document=future.get();
review=document.toObject(Review.class);
reviewList.add(review);
}
return reviewList;
}
public String updateReview(Review review) throws ExecutionException, InterruptedException {
Firestore dbFirestore= FirestoreClient.getFirestore();
ApiFuture<WriteResult> collectionApiFuture=dbFirestore.collection(COLLECTION_NAME).document(review.getName()).set(review);
return collectionApiFuture.get().getUpdateTime().toString();
}
public String deleteReview(String name) throws ExecutionException, InterruptedException {
Firestore dbFirestore= FirestoreClient.getFirestore();
ApiFuture<WriteResult> collectionApiFuture=dbFirestore.collection(COLLECTION_NAME).document(name).delete();
return "Document with Review ID "+name+" has been deleted successfully";
}
}
My Controller class
package com.example.firebase.springbootfirebasedemo.controller;
import com.example.firebase.springbootfirebasedemo.entity.Review;
import com.example.firebase.springbootfirebasedemo.service.ReviewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
@RestController
@RequestMapping("/api")
public class ReviewController {
@Autowired
private ReviewService reviewService;
@PostMapping(path = "/reviews", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public String saveReview(@ModelAttribute Review review, @RequestParam(value = "file",required = false) MultipartFile file)
throws ExecutionException, InterruptedException,IOException {
return reviewService.saveReview(review, file);
}
@GetMapping("/reviews/{name}")
public Review getReview(@PathVariable String name) throws ExecutionException, InterruptedException {
return reviewService.getReviewDetailsByname(name);
}
@GetMapping("/reviews")
public List<Review> getAllReviews() throws ExecutionException, InterruptedException {
return reviewService.getAllReviews();
}
@PutMapping("/reviews")
public String updateReview(@RequestBody Review review) throws ExecutionException, InterruptedException {
return reviewService.updateReview(review);
}
@DeleteMapping("/reviews/{name}")
public String deleteReview(@PathVariable String name) throws ExecutionException, InterruptedException {
return reviewService.deleteReview(name);
}
}
Using the above code I was able to save the image with a image name on Google Cloud Storage, but the image is empty.The size of the file is also showing zero bytes.Please help.Thank you.
Solution
You are only storing the Google Cloud Storage file metadata: BlobInfo
, hence you will end up with a file without any content but still created.
You should copy the file content (byte[]
) to the newly created file using the Blob
type:
@Service
public class ReviewService {
public String saveReview(Review review, MultipartFile file) throws ExecutionException, InterruptedException, IOException {
BlobInfo blobInfo = storage.create(BlobInfo.newBuilder(BUCKET_NAME, file.getOriginalFilename()).build());
Blob blob = storage.create(blobInfo, file.getBytes());
System.out.println(blobInfo.getMediaLink());
Firestore dbFirestore = FirestoreClient.getFirestore();
ApiFuture<WriteResult> collectionApiFuture = dbFirestore.collection(COLLECTION_NAME).document(review.getName()).set(review);
return collectionApiFuture.get().getUpdateTime().toString();
}
// ...
}
Answered By - tmarwen