I am using blobstore API to upload an image to my app. This works fine locally, which means image is successfully uploaded and callback works as well. But when I am sending the multipart request to the uploadurl returned by createUploadUrl from the server, it always gives me 404 not found error.
Is it possible that blobstore is not enabled for my app? Why can't I see my blobstore in the google cloud console? I have to go to here https://appengine.google.com/blobstore/ to see my blobs.
Code on the app side: doPost handles callback and doGet returns the uploadUrl (both within same servlet /_ah/admin/new_image). doPost(call back handler code) is never triggered and neither is image is uploaded.
#Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("image");
ImagesService imagesService = ImagesServiceFactory.getImagesService();
String imageUrl = imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(blobKeys.get(0)));
Long businessId = Long.parseLong(req.getParameter("business_id"));
String linkUrl = req.getParameter("link_url");
Long id = Long.parseLong(req.getParameter("advertisement_id"));
AdvertisementManager.addNewAdvertisement(id, imageUrl, linkUrl, businessId);
}
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
PrintWriter out = resp.getWriter();
resp.setContentType( "text/html" );
String uploadUrl = blobstoreService.createUploadUrl("");
Logger.getLogger("").log(Level.WARNING,uploadUrl);
out.print(uploadUrl);
}
Code to upload an image: First send a get request to get the upload url, then sends the multipart request with the image File
public static void upload(Long id, File file, String linkUrl, Long businessId){
HttpClient httpclientget = HttpClientBuilder.create().build();
HttpGet httpget = new HttpGet("http://app-url/_ah/admin/new_image");
String uploadUrl = "";
try {
HttpResponse responseGet = httpclientget.execute(httpget);
uploadUrl = EntityUtils.toString(responseGet.getEntity());
Logger.getLogger("").log(Level.WARNING,uploadUrl);
} catch (Exception e) {
e.printStackTrace();
}
HttpClient httpclient = HttpClientBuilder.create().build();
HttpPost httpPost = null;
String uri=null;
try {
URIBuilder builder = new URIBuilder(uploadUrl);
builder.setParameter("advertisement_id", id.toString());
builder.setParameter("link_url", linkUrl);
builder.setParameter("business_id", businessId.toString());
uri=builder.build().toString();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
httpPost = new HttpPost(uri);
System.out.println(uri);
if (file!=null){
MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();
reqEntity.addBinaryBody("image", file, ContentType.create("image/jpeg"), "ad.jpg");
httpPost.setEntity(reqEntity.build());
}
try {
HttpResponse response = httpclient.execute(httpPost);
System.out.println(response);
} catch (Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
AFAIK the /_ah/* space is reserved for internal GAE services and you shouldn't use it. The reason you are getting a 404 is probably Google preventing you from deploying that servlet, try changing the URL.
Related
I am uploading a File from GWT to a different domain
File Uploads well , But the response i sent from the server always reaches as "null" at the client side
response.setContentType("text/html");
response.setHeader("Access-Control-Allow-Origin", "*");
response.getWriter().print("TEST");
response is NULL only when i upload the file on a different domain ... (on same domain all is OK)
I also see this in GWT documentation
Tip:
The result html can be null as a result of submitting a form to a different domain.
http://www.gwtproject.org/javadoc/latest/com/google/gwt/user/client/ui/FormPanel.SubmitCompleteEvent.html
Is there any way I can receive back a response at my client side when i am uploading file to a different domain
There are 2 possible answer:
Use JSONP Builder
JsonpRequestBuilder requestBuilder = new JsonpRequestBuilder();
requestBuilder.requestObject(url, new AsyncCallback<FbUser>() {
#Override
public void onFailure(Throwable ex) {
throw SOMETHING_EXCEPTION(ex);
}
#Override
public void onSuccess(ResponseModel resp) {
if (resp.isError()) {
// on response error on something
log.error(resp.getError().getMessage())
log.error(resp.getError().getCode())
}
log.info(resp.getAnyData())
}
Not to use GWT to upload, rather use other client like apache HttpClient
public uploadFile() {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
FileBody bin = new FileBody(new File(UPLOADED_FILE));
long size = bin.getContentLength();
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("PART", bin);
String content = "-";
try {
httpPost.setEntity(reqEntity);
HttpResponse response = httpClient.execute(httpPost, localContext);
HttpEntity ent = response.getEntity();
InputStream st = ent.getContent();
StringWriter writer = new StringWriter();
IOUtils.copy(st, writer);
content = writer.toString();
} catch (IOException e) {
return "false";
}
return content;
}
Hope it helps
I want to make a request to my organisation api's. The request contains Headers, UserName, Password, & Cookie for session management.
Below is the actual code (in HttpClient) which I want to rewrite using Retrofit. I have heard that HttpClient libraries have been deprecated or someting so have opted Retrofit. I expect the response with 200 status code.
public static CookieStore cookingStore = new BasicCookieStore();
public static HttpContext context = new BasicHttpContext();
public String getAuth(String login,String password) {
String resp = null;
try {
String url = DOMAIN+"myxyzapi/myanything";
context.setAttribute(HttpClientContext.COOKIE_STORE, cookingStore);
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
String log = URLEncoder.encode(login, "UTF-8");
String pass = URLEncoder.encode(password, "UTF-8");
String json = "username="+log+"&password="+pass+"&maintain=true&finish=Go";
StringEntity entity = new StringEntity(json);
post.setEntity(entity);
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
HttpResponse response = client.execute(post,context);
resp = EntityUtils.toString(response.getEntity());
accountPoller();
} catch(Exception a) {
log.info("Exception in authentication api:"+a.getMessage().toString());
}
return resp;
}
Below is my code where I can't figure out how to pass the context with request. HttpResponse response = client.execute(post,**context**); using retrofit.
I don't even know if I have made my retrofit request right.
try {
String log = URLEncoder.encode(login, "UTF-8");
String pass = URLEncoder.encode(password, "UTF-8");
RequestBody formBody = new FormBody.Builder()
.add("username=", xyz)
.add("password=", mypass)
.add("&maintain=", "true")
.add("finish=", "Go")
.build();
String url = www.xyz.com+"myxyzapi/myanything";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).post(formBody).addHeader("Content-Type", "application/x-www-form-urlencoded").build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myresp = response.body().string();
}
}
});
} catch(Exception a) {
a.getMessage();
}
You have to catch exception and use this class.
retrofit2.HttpException
retrofit2
Class HttpException
int
code()
HTTP status code.
String
message()
HTTP status message.
Response
response()
The full HTTP response.
This is the log from the server:
POST Request reader reads:--3cd58f21-8ffa-46a0-b1c0-0e4660c2ca28
POST Request reader reads:Content-Disposition: form-data; name="device"
POST Request reader reads:Content-Length: 163
POST Request reader reads:
POST Request reader reads:{"deviceId":"5ccf7f0fb7b1","manufacturer":"Wow Lamp","name":"Wow-b7b1","type":"lamp","userId":"amzn1.account.AGGL3JOPQ3UTF74KQY2TJCYSYNAQ","timer":0,"chosen":true}
POST Request reader reads:--3cd58f21-8ffa-46a0-b1c0-0e4660c2ca28--
The result above is what the reader read from the request. But if getParameter is called from the request instance, the parameter map is null.
This is the content of the parameter map:
POST Request:{}
As you can see, the map contains no parameter, but the reader can read the data sent by the client.
This is the code of the server:
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException
{
System.out.println("POST Request:" + req.getParameterMap());
if(isPostRequestValid(req))
{
try
{
handleRequest(req);
}
catch (JSONException e)
{
e.printStackTrace();
}
}
sendResponse(resp);
try
{
BufferedReader reader = req.getReader();
String inputLine;
while((inputLine = reader.readLine()) != null)
{
System.out.println("POST Request reader reads:" + inputLine);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
There must be some coding mistake in the client side
This is the code of the client:
new Thread(new Runnable() {
#Override
public void run() {
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM) //this is what I say in my POSTman (Chrome plugin)
.addFormDataPart("device", device)
.build();
Request request = new Request.Builder()
.url(Constant.BASE_URL + "update_device.html")
.post(requestBody)
.build();
try {
Response response = client.newCall(request).execute();
String responseString = response.body().string();
response.body().close();
// do whatever you need to do with responseString
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
But the client side did use form data, so what can be wrong here?
I have solve the problem by updating my OKHttpClient to version 3.6 and then change the request body part of my code to this
RequestBody formBody = new FormBody.Builder()
.add("key", "value")
.build();
It seems that my version of OKHttpClient before does not include the functionality to send parameters of content type application/x-www-form-urlencoded.
Before updating, OKHttpClient can only send parameter of content type multipart/form-data. But for the servlet side, I was unable to parse this content type. I tried using the method getPart("key") however an exception was thrown after accessing that method.
So, updating OKHttpClient to version 3.6 will allow me to use the FormBody class which sends request parameters with application/x-www-form-urlencoded content type. This way, the servlet side can now get the parameters via request.getParameter("key") method.
HTTP POST parameters are received in a Servlet via request parameters, not by reading the request body.
I am sending a image from android phone to server which is a servlet I am using the HttpClient and HttpPost for this and ByteArrayBody for storing the image before sending.
how do i extract the image from the post request in Servlet.
Here is my code for sending the post request
String postURL = //server url;
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(postURL);
ByteArrayBody bab = new ByteArrayBody(imageBytes,"file_name_ignored");
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("source", bab);
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
Use something like commons fileupload.
There are examples in the Apache docs, and all over the web.
Servlet 3.0 has support for reading multipart data. MutlipartConfig support in Servlet 3.0
If a servelt is annotated using #MutlipartConfig annotation, the container is responsible for making the Multipart parts available through
HttpServletRequest.getParts()
HttpServletRequest.getPart("name");
use http://commons.apache.org/fileupload/using.html
private DiskFileItemFactory fif = new DiskFileItemFactory();
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if(!isMultipart)
throw new ServletException("upload using multipart");
ServletFileUpload upload = new ServletFileUpload(fif);
upload.setSizeMax(1024 * 1024 * 10 /* 10 mb */);
List<FileItem> items;
try {
items = upload.parseRequest(req);
} catch (FileUploadException e) {
throw new ServletException(e);
}
if(items == null || items.size() == 0)
throw new ServletException("No items uploaded");
FileItem item = items.get(0);
// do something with file item...
}
I am using the apache library. I have created a class which sends a post request to a servlet. I have set up the parameters for the client and i have created a HTTP post object to be sent but for some reason when i excute the request i get a reposnse that says the get method is not supported(which is true cause i have only made a dopost method in my servlet). It seems that a get request is being sent but i dont know why. The post method worked before but i started gettng http error 417 "Expectation Failed" due to me not setting the protocal version but i fixed this by adding paramenters.
below is my class where you see a HTTPpost object being created and exectued. I have a response handler method but i took it out of my code below because it has nothing to do with my problem.
I know a HTTP GET is being sent because of the reponse mesage that is returned says. The specified HTTP method is not allowed for the requested resource (HTTP method GET is not supported by this URL).
Thanks in advance.
P.s i am developing for android.
public class HTTPrequestHelper {
private final ResponseHandler<String> responseHandler;
private static final String CLASSTAG = HTTPrequestHelper.class.getSimpleName();
private static final DefaultHttpClient client;
static{
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
params.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.UTF_8);
///params.setParameter(CoreProtocolPNames.USER_AGENT, "Android-x");
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15000);
params.setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(
new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(
new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
client = new DefaultHttpClient(cm,params);
}
public HTTPrequestHelper(ResponseHandler<String> responseHandler) {
this.responseHandler = responseHandler;
}
public void performrequest(String url, String para)
{
HttpPost post = new HttpPost(url);
StringEntity parameters;
try {
parameters = new StringEntity(para);
post.setEntity(parameters);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BasicHttpResponse errorResponse =
new BasicHttpResponse(
new ProtocolVersion("HTTP_ERROR", 1, 1),
500, "ERROR");
try {
client.execute(post, this.responseHandler);
}
catch (Exception e) {
errorResponse.setReasonPhrase(e.getMessage());
try {
this.responseHandler.handleResponse(errorResponse);
}
catch (Exception ex) {
Log.e( "ouch", "!!! IOException " + ex.getMessage() );
}
}
}
I tried added the allow header to the request but that did not work as well but im not sure if i was doing right. below is the code.
client.addRequestInterceptor(new HttpRequestInterceptor() {
#Override
public void process(HttpRequest request, HttpContext context)
throws HttpException, IOException {
//request.addHeader("Allow", "POST");
}
});
How do you know that a HTTP GET is actually being sent? Examining the http packets sent by your client or received by the server would be helpful here
You catch and swallow UnsupportedEncodingException when constructing the Post's parameters - what happens if you encounter this exception while setting parameters? Your code as is today will still attempt to execute the POST.