Shikha Shah
Shikha Shah

Reputation: 753

Upload files to GAE via android

I have been working on Google app engine since 3 days and finally encountered this issue that I am not able to resolve..Did lot of research but could find anything convincing. M

After setting up my Google app Engine account, When I call my application url "my-app-id.appspot.com/myservlet" , the simple Servlet on GAE is able to write .txt file in my Google bucket . Code snippet for the same is here:

 fetchurl.java 

             DefaultHttpClient hc=new DefaultHttpClient();
             ResponseHandler <String> res=new BasicResponseHandler();
             HttpGet postMethod=new HttpGet("http://my-app-id.appspot.com/uploadservlet");

             String response=hc.execute(postMethod,res);

uploadservlet.java

  An example @ Complete Sample App at this link:
  https://developers.google.com/appengine/docs/java/googlestorage/overview

Now My problem is when I send some file through POST method using multi-part , the Servlet @ app engine doesnt work and I get error message "Filenotfound" in eclipse .

.java file at Android side

  urlString = "http://my-app-id.appspot.com/uploadservlet";
  URL url = new URL(urlString);

             // Open a HTTP connection to the URL
             conn = (HttpURLConnection) url.openConnection();
             conn.setConnectTimeout(90000);

             // Allow Inputs
             conn.setDoInput(true);

             // Allow Outputs
             conn.setDoOutput(true);

             // Don't use a cached copy.
             conn.setUseCaches(false);

             // Use a post method.
             conn.setRequestMethod("POST");

             isOK = true;

             conn.setRequestProperty("Connection", "Keep-Alive");

             conn.setRequestProperty("Content-Type",
                     "multipart/form-data;boundary=" + boundary);

             DataOutputStream dos = new DataOutputStream(conn.getOutputStream());


            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=param1;filename="
                            + param1 + "" + lineEnd);
            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + lineEnd);
            Log.e(Tag, "Param1 are written");

            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=param2;filename="
                            + param2 + "" + lineEnd);
            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + lineEnd);
            Log.e(Tag, "Param2 are written");



            FileInputStream fileInputStream = new FileInputStream(new File(
                    path));
            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=uploadedfile;filename="
                         + path + "" + lineEnd);
            dos.writeBytes(lineEnd);

            Log.e(Tag, "Headers are written");

             // create a buffer of maximum size

             int bytesAvailable = fileInputStream.available();
             int maxBufferSize = 1000;
             // int bufferSize = Math.min(bytesAvailable, maxBufferSize);
             byte[] buffer = new byte[bytesAvailable];

             // read file and write it into form...

             int bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);

             while (bytesRead > 0) 
             {
                 dos.write(buffer, 0, bytesAvailable);
                 bytesAvailable = fileInputStream.available();
                 bytesAvailable = Math.min(bytesAvailable, maxBufferSize);
                 bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
             }

             // send multipart form data necesssary after file data...
             //dos.writeBytes(lineEnd);
             dos.writeBytes(twoHyphens + boundary + lineEnd);
             dos.writeBytes(lineEnd);
             dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

I am wondering if this approach is even right. If not what are another solutions..I also looked at blobstorage but it does the same , writing file to bucket not uploading..Please help me guys...Anything would great and appreciated!!!

 Servlet code to handle file upload and save to Google storage--

 @MultipartConfig   
 @SuppressWarnings("serial")
   public class SecondtrygoogleServlet extends HttpServlet 
   {
public static String BUCKETNAME = "androidbucket";
public static String FILENAME = "shikhatry.txt";

private static final long serialVersionUID = 1L;


private static final int THRESHOLD_SIZE = 1024 * 1024 * 3; // 3MB
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
private static final int REQUEST_SIZE = 1024 * 1024 * 50; // 50MB



public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 
{
    // checks if the request actually contains upload file
    if (!ServletFileUpload.isMultipartContent(request)) {
        // if not, we stop here
        return;
    }

    response.setContentType("text/plain");
    response.getWriter().println("Hello, test1 world");

    // configures some settings
    DiskFileItemFactory factory = new DiskFileItemFactory();
    factory.setSizeThreshold(THRESHOLD_SIZE);
    factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

    ServletFileUpload upload = new ServletFileUpload(factory);
    upload.setFileSizeMax(MAX_FILE_SIZE);
    upload.setSizeMax(REQUEST_SIZE);
    java.io.PrintWriter out = response.getWriter( );

    try {
            // parses the request's content to extract file data
            List<?> formItems = upload.parseRequest(request);
            out.println("Number of fields: " + formItems.size());
            Iterator<?> iter = formItems.iterator();


            // iterates over form's fields
            while (iter.hasNext()) 
            {
                out.println("Inside while loop");
                FileItem item = (FileItem) iter.next();
                // processes only fields that are not form fields
                if (!item.isFormField()) 
                {

                    String temp = item.getFieldName();
                    out.println("Parameter Name"+temp);

                    if(temp.equals("uploadedfile"))
                    {
                        String fileName = new File(item.getName()).getName();
                        FILENAME = fileName+".txt";
                        out.println("Filename"+fileName);


                        FileService fileService = FileServiceFactory.getFileService();
                        GSFileOptionsBuilder optionsBuilder = new GSFileOptionsBuilder()
                        .setBucket(BUCKETNAME)
                        .setKey(FILENAME)
                        .setMimeType("text/html") //audio/mp3 text/html
                        .setAcl("public_read")
                        .addUserMetadata("myfield1", "my field value");


                     AppEngineFile writableFile =
                         fileService.createNewGSFile(optionsBuilder.build());

                     // Open a channel to write to it
                     boolean lock = false;
                     FileWriteChannel writeChannel =
                         fileService.openWriteChannel(writableFile, lock);


                     // Different standard Java ways of writing to the channel
                     // are possible. Here we use a PrintWriter:

                     InputStream inputStream = item.getInputStream();
                     int readBytes = 0;
                     byte[] buffer = new byte[10000];



                     while ((readBytes = inputStream.read(buffer, 0, 10000)) != -1) 
                     {
                        writeChannel.write(ByteBuffer.wrap(buffer));

                     }

                     inputStream.close();

                     writeChannel.closeFinally();
                     response.getWriter().println("Done writing...");

                }
                else if(temp.equals("param1"))
                {
                    out.println("Inside param1");
                    //String param1Val = new File(item.getName()).getName();                        
                    //BUCKETNAME = param1Val;
                }
                else if(temp.equals("param2"))
                {
                    out.println("Inside param2");
                    //String param2Val = new File(item.getName()).getName();

                    //BUCKETNAME = param2Val;


                }
            }
        }
        request.setAttribute("message", "Upload has been done successfully!");
    } catch (Exception ex) {
        request.setAttribute("message", "There was an error: " + ex.getMessage());
    }


}

Upvotes: 0

Views: 1041

Answers (1)

Stuart Langley
Stuart Langley

Reputation: 7054

Options are:

a. Use createUploadURL with a form to upload large files, or

b. Use your method and then decode parse the upload and write to the blobstore yourself in the servlet (files would need to be less than 32MB), or

c. Use Google Cloud Storage API to write directly to GCS and then post the uploaded file names to your App.

Upvotes: 1

Related Questions