package in.partake.controller.api.image;
import in.partake.base.PartakeException;
import in.partake.base.TimeUtil;
import in.partake.base.Util;
import in.partake.controller.api.AbstractPartakeAPI;
import in.partake.model.IPartakeDAOs;
import in.partake.model.UserEx;
import in.partake.model.access.Transaction;
import in.partake.model.dao.DAOException;
import in.partake.model.dao.PartakeConnection;
import in.partake.model.dao.access.IUserImageAccess;
import in.partake.model.dto.UserImage;
import in.partake.resource.ServerErrorCode;
import in.partake.resource.UserErrorCode;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.JsonNodeFactory;
import org.codehaus.jackson.node.ObjectNode;
import play.mvc.Http.MultipartFormData.FilePart;
import play.mvc.Result;
/**
* Upload images, and gets recent image ids if necessary.
* @author shinyak
*
*/
public class CreateImageAPI extends AbstractPartakeAPI {
public static Result post() throws DAOException, PartakeException {
return new CreateImageAPI().execute();
}
@Override
protected Result doExecute() throws DAOException, PartakeException {
UserEx user = ensureLogin();
ensureValidSessionToken();
FilePart filePart = request().body().asMultipartFormData().getFile("file");
if (filePart == null)
return renderInvalid(UserErrorCode.INVALID_NOIMAGE);
File file = filePart.getFile();
String contentType = filePart.getContentType();
if (file == null)
return renderInvalid(UserErrorCode.INVALID_NOIMAGE);
if (contentType == null)
return renderInvalid(UserErrorCode.INVALID_IMAGE_CONTENTTYPE);
// IE sends jpeg file using contentType = "image/pjpeg". We should handle this here.
if ("image/pjpeg".equals(contentType))
contentType = "image/jpeg";
if (!Util.isImageContentType(contentType))
return renderInvalid(UserErrorCode.INVALID_IMAGE_CONTENTTYPE);
int limit = optIntegerParameter("limit", 1);
limit = Util.ensureRange(limit, 1, 100);
List<String> imageIds = new CreateImageAPITransaction(user, file, contentType, limit).execute();
ObjectNode obj = new ObjectNode(JsonNodeFactory.instance);
obj.put("imageId", imageIds.get(0));
ArrayNode imageIdArray = obj.putArray("imageIds");
for (String imageId : imageIds) {
imageIdArray.add(imageId);
}
// We should return text/plain or text/html for MS-IE here.
// TODO: Should use Accept header instead of this.
if (optBooleanParameter("ensureTextPlain", false))
return renderOKWith(obj, "text/plain");
else
return renderOK(obj);
}
}
class CreateImageAPITransaction extends Transaction<List<String>> {
private UserEx user;
private File file;
private String contentType;
private int limit;
CreateImageAPITransaction(UserEx user, File file, String contentType, int limit) {
this.user = user;
this.file = file;
this.contentType = contentType;
this.limit = limit;
}
// TODO: We should not load image in memory here. However, sending image from DB directly will cause
// another problem, e.g. DoS.
public List<String> doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException {
IUserImageAccess dao = daos.getImageAccess();
byte[] foreImageByteArray;
try {
foreImageByteArray = Util.getContentOfFile(file);
} catch (IOException e) {
throw new PartakeException(ServerErrorCode.ERROR_IO);
}
String imageId = dao.getFreshId(con);
UserImage imageEmbryo = new UserImage(imageId, user.getId(), contentType, foreImageByteArray, TimeUtil.getCurrentDateTime());
dao.put(con, imageEmbryo);
if (limit == 1)
return Collections.singletonList(imageId);
else
return dao.findIdsByUserId(con, user.getId(), 0, limit);
}
}