简体   繁体   中英

Mobile Backend Starter - Upload to AppEngine Blobstore

如何使用Mobile Backend Starter或Google Cloud Endpoints将文件从Android上传到Google App Engine Blobstore?

Sharing my expirience with Mobile Backend Starter.

To obtain uploading and downloading urls you need to add this two methods to CloudBackend.java class to make urls accessible from the Activity:

public String getUploadBlobURL(String bucketName, String path, String accessMode) {

        String url = null;
        try {
            url = getMBSEndpoint().blobEndpoint()
                    .getUploadUrl(bucketName, path, accessMode).execute()
                    .getShortLivedUrl();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return url;
    }

public String getDownloadBlobURL(String bucketName, String path) {

        String url = null;
        try {
            url = getMBSEndpoint().blobEndpoint()
                    .getDownloadUrl(bucketName, path).execute()
                    .getShortLivedUrl();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return url;
    }

Then you can use urls to stream bytes to Google Cloud Storage with the helping of standard client libraries.

Below I'll give you examples how to use them.

For uploading file to the Google Cloud Storage you may use something similar to this:

Activity

File fileUp = new File(Environment.getExternalStorageDirectory(), fileName);
        new AsyncBlobUploader(this, mProcessingFragment.getCloudBackend()).execute(fileUp);

AsyncTask

public class AsyncBlobUploader extends AsyncTask<File, Void, String> {
    private Context context;
    private ProgressDialog pd;
    private CloudBackend cb;

    public AsyncBlobUploader(Context context, CloudBackend cb) {
        this.context = context;
        this.cb = cb;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pd = ProgressDialog.show(context, null,
                "Loading... Please wait...");
        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        pd.setIndeterminate(true);
        pd.setCancelable(true);
        pd.show();
    }

    protected String doInBackground(File... files) {
        File file = files[0];
        String uploadUrl = cb.getUploadBlobURL(bucketName, file.getName(),"PUBLIC_READ_FOR_APP_USERS");
        String url = uploadUrl.split("&Signature")[0]; // url without Signature

        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(url);

        FileBody filebody = new FileBody(file,ContentType.create(getMimeType(file
                .toString())), file.getName());

        MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();        
        multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntity.addPart("file", filebody);
        httppost.setEntity(multipartEntity.build());
        System.out.println( "executing request " + httppost.getRequestLine( ) );
        try {
            HttpResponse response = httpclient.execute( httppost );
            Log.i("response", response.getStatusLine().toString());
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        httpclient.getConnectionManager( ).shutdown( );

        return (String) uploadUrl;
    }

    protected void onPostExecute(String result) {

        pd.dismiss();
        Log.d("BlobUrl", result);

    }

    public static String getMimeType(String url) {
        String type = null;
        String extension = MimeTypeMap.getFileExtensionFromUrl(url);
        if (extension != null) {
            MimeTypeMap mime = MimeTypeMap.getSingleton();
            type = mime.getMimeTypeFromExtension(extension);
        }
        return type;
    }
}

MultipartEntityBuilder class is not included into android standard libraries so you need to download httpclient and include into your project.

Pay attention to this line String url = uploadUrl.split("&Signature")[0]; where I am cutting off url signature. (With url signature I am getting 503 Internal Server Error but without it everything works as expected. I do not why this happens.)

For downloading you can use this snippet:

Activity

File fileDown = new File(Environment.getExternalStorageDirectory(),
                fileName); //file to create
        new AsyncBlobDownloader(imageView, mProcessingFragment.getCloudBackend())
            .execute(fileDown);

AsyncTask

public class AsyncBlobDownloader extends AsyncTask<File, Integer, File> {
    private ImageView imageView;
    private ProgressDialog pd;
    private CloudBackend cb;

    public AsyncBlobDownloader(ImageView imageView, CloudBackend cb) {
        this.imageView = imageView;
        this.cb = cb;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pd = ProgressDialog.show(imageView.getContext(), null,
                "Loading... Please wait...");
        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        pd.setCancelable(true);
        pd.show();
    }

    protected File doInBackground(File... files) {
        File file = files[0];
        String downloadUrl = cb.getDownloadBlobURL(bucketName,
                file.getName());
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(downloadUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                Log.i("Response",
                        "Server returned HTTP " + connection.getResponseCode()
                                + " " + connection.getResponseMessage());
            }
            int fileLength = connection.getContentLength();

            input = connection.getInputStream();
            output = new FileOutputStream(file);

            byte data[] = new byte[4096];

            int count;
            while ((count = input.read(data)) != -1) {
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }    
        return file;
    }

    protected void onPostExecute(File result) {    
        pd.dismiss();
        imageView.setImageURI(Uri.fromFile(result));   
    }   
}

NOTE: To use Google Cloud Storage you need to enable billing. Also you need to create bucket in GCS.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM