1
votes

I'm trying to upload image file to Blobstore using Google Cloud Endpoints. The code below successfully stores image in Blobstore but doesn't create the Entity "Image" in Datastore and so it doesn't add the Image Reference to the MyUser Entity (I use Objectify to store entities in Datastore).

Plus when i upload an image i get "404 NOT_FOUND" error as response...but the image is correctly stored in the Blobstore.

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
        <title>404 NOT_FOUND</title>
    </head>
    <body text=#000000 bgcolor=#ffffff>
        <h1>Error: NOT_FOUND</h1>
    </body>
</html>

My Endpoints Code

 @Api(
        name = "imageManager"
)
public class ImageManager {

    BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

    @ApiMethod(name = "urlToUpload", httpMethod = "get")
    public Image urlToUpload(){
        Image image = new Image();
        image.url = blobstoreService.createUploadUrl("/imageManager/upload");

        return image;
    }

This is the upload handler:

@ApiMethod(name = "upload", httpMethod = "post")
    public Image upload(HttpServletRequest httpServletRequest) throws BadRequestException, NotFoundException, UnauthorizedException {
        String op = httpServletRequest.getParameter("op");
        if(op == null) throw new BadRequestException("op is null");

        Image image = null;

        if(op.equalsTo("registerUser") image = this.uploadRegisterUser(httpServletRequest);
        return image;
    }

UploadRegisterUser:

private Image uploadRegisterUser(HttpServletRequest httpServletRequest) throws NotFoundException {

        Long userId = Long.parseLong(httpServletRequest.getParameter("userId"));

        MyUser user = ofy().load().type(MyUser.class).filter("id",userId).first().now();

        if(user == null) throw new NotFoundException("User not found");

        Ref<Image> imageRef = this.saveImage(httpServletRequest, wUser, null);

        user.profileImage = imageRef;
        ofy().save().entity(wUser).now();

        return imageRef.getValue();
    }

SaveImage:

private Ref<Image> saveImage(HttpServletRequest httpServletRequest, MyUser user, String label){

        List<BlobKey> blobs = blobstoreService.getUploads(httpServletRequest).get("file");
        Image image = new Image();
        image.key = blobs.get(0).getKeyString();
        image.user = Ref.create(user);
        image.date = new Date();
        image.label = label;

        return Ref.create(ofy().save().entity(image).now());
    }

Where i'm wrong? Thanks in advance.

1
It seems that the name of the callback method in blobstoreService.createUploadUrl() is wrong. But i also tried with myAppId.appspot.com/_ah/api/imageManager/v1/upload, /_ah/api/imageManager/v1/upload and just "upload"....but with no luck! - Mattia Campana

1 Answers

1
votes

I don't think your handler was called at all. The cloud endpoint paths are always going to be after /_ah/api/.... So your upload handler was simply not mapped to the blobstore upload path. You'll have to create a separate servlet that's mapped to /upload and add that to your Web.xml. At least that's my solution so far.

Create a seperate servlet like this one:

public class UploadgimageServlet extends HttpServlet {


private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

    public void doPost(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {

        Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(req);
        BlobKey blobKey = blobs.get(“file");

        if (blobKey == null) {
            res.sendRedirect("/");
        } else {
            res.sendRedirect("http://localhost:8888/getimage?blob-key=" + blobKey.getKeyString());
        }
    }
}

Add these to your web.xml

<servlet>
     <servlet-name>Uploadgimage</servlet-name>
    <servlet-class>com.yourcomp.UploadgimageServlet</servlet-class>
 </servlet>

 <servlet-mapping>
    <servlet-name>Uploadgimage</servlet-name>
    <url-pattern>/imageManager/upload</url-pattern>  //Based on your original URL
  </servlet-mapping>

Good luck!