Upload file with Azure Storage using SAS (Shared Access Signature) - android

I know that there is library available for uploading the file using Azure Storage. I have refer this for same.
But, they have not give information for how to use SAS with that. I have account name, and sas url for access and upload file there. But I don't know how to use that for uploading file.
If I use above mention library it shows me invalid storage connection string because I am not passing the key in it (Which is not required with sas). So I am confused how I can upload file.
I have refer this documentation also for uploading file using sas. but not getting proper steps to do this. They have made demo for their windows app. I want to have that in android with use of sas.
Update
I have try with below code with reference to the console app made by Azure to check and access SAS.
try {
//Try performing container operations with the SAS provided.
//Return a reference to the container using the SAS URI.
//CloudBlockBlob blob = new CloudBlockBlob(new StorageUri(new URI(sas)));
String[] str = userId.split(":");
String blobUri = "https://myStorageAccountName.blob.core.windows.net/image/" + str[1] + "/story/" + storyId + "/image1.jpg" + sas.toString().replaceAll("\"","");
Log.d(TAG,"Result:: blobUrl 1 : "+blobUri);
CloudBlobContainer container = new CloudBlobContainer(new URI(blobUri));
Log.d(TAG,"Result:: blobUrl 2 : "+blobUri);
CloudBlockBlob blob = container.getBlockBlobReference("image1.jpg");
String filePath = postData.get(0).getUrl().toString();
/*File source = new File(getRealPathFromURI(getApplicationContext(),Uri.parse(filePath))); // File path
blob.upload(new FileInputStream(source), source.length());*/
Log.d(TAG,"Result:: blobUrl 3 : "+blobUri);
//blob.upload(new FileInputStream(source), source.length());
//blob.uploadText("Hello this is testing..."); // Upload text file
Log.d(TAG, "Result:: blobUrl 4 : " + blobUri);
Log.d(TAG, "Write operation succeeded for SAS " + sas);
response = "success";
//Console.WriteLine();
} catch (StorageException e) {
Log.d(TAG, "Write operation failed for SAS " + sas);
Log.d(TAG, "Additional error information: " + e.getMessage());
response = e.getMessage();
} catch (FileNotFoundException e) {
e.printStackTrace();
response = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
response = e.getMessage();
} catch (URISyntaxException e) {
e.printStackTrace();
response = e.getMessage();
} catch (Exception e){
e.printStackTrace();
response = e.getMessage();
}
Now, when I upload text only it says me below error
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
Now, my requirement is to upload Image file. So when I uncomment code for uploading image file it is not giving me any error but even not uploading image file.

#kumar kundal
The mechanism that you have explained is completely right.
Below is the more detailed answer about uploading profile image to the Azure Server.
First create SAS url to upload Image(or any file) to blob storage:
String sasUrl = "";
// mClient is the MobileServiceClient
ListenableFuture<JsonElement> result = mClient.invokeApi(SOME_URL_CREATED_TO_MAKE_SAS, null, "GET", null);
Futures.addCallback(result, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement result) {
// here you will get SAS url from server
sasUrl = result; // You need to parse it as per your response
}
#Override
public void onFailure(Throwable t) {
}
});
Now, you have sasURL with you. That will be something like the below string:
sv=2015-04-05&ss=bf&srt=s&st=2015-04-29T22%3A18%3A26Z&se=2015-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=F%6GRVAZ5Cdj2Pw4tgU7IlSTkWgn7bUkkAg8P6HESXwmf%4B
Now, you need to append the sas url with your uploading url. See below code in which I have appended the SAS url with my uploading request.
try {
File source = new File(filePath); // File path
String extantion = source.getAbsolutePath().substring(source.getAbsolutePath().lastIndexOf("."));
// create unique number to identify the image/file.
// you can also specify some name to image/file
String uniqueID = "image_"+ UUID.randomUUID().toString().replace("-", "")+extantion;
String blobUri = MY_URL_TO_UPLOAD_PROFILE_IMAGE + sas.replaceAll("\"","");
StorageUri storage = new StorageUri(URI.create(blobUri));
CloudBlobClient blobCLient = new CloudBlobClient(storage);
CloudBlobContainer container = blobCLient.getContainerReference("");
CloudBlockBlob blob = container.getBlockBlobReference(uniqueID);
BlobOutputStream blobOutputStream = blob.openOutputStream();
byte[] buffer = fileToByteConverter(source);
ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);
int next = inputStream.read();
while (next != -1) {
blobOutputStream.write(next);
next = inputStream.read();
}
blobOutputStream.close();
// YOUR IMAGE/FILE GET UPLOADED HERE
// IF YOU HAVE FOLLOW DOCUMENT, YOU WILL RECEIVE IMAGE/FILE URL HERE
} catch (StorageException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
I hope this information help you lot for uploading the file using blob storage.
Please let me know if you have any doubt apart from this. I can help in that.

Uploading a pic to BLOB storage . I got it after searching for hours .Take a look :-
Uploading the photo image is a multistep process:
First you take a photo, and insert a TodoItem row into the SQL database that contains new meta-data fields used by Azure Storage.
A new mobile service SQL insert script asks Azure Storage for a Shared Access Signature (SAS).
That script returns the SAS and a URI for the blob to the client.
The client uploads the photo, using the SAS and blob URI.
So what is a SAS?
It's not safe to store the credentials needed to upload data to the Azure Storage service inside your client app. Instead, you store these credentials in your mobile service and use them to generate a Shared Access Signature (SAS) that grants permission to upload a new image. The SAS, a credential with a 5 minute expiration, is returned securely by Mobile Services to the client app. The app then uses this temporary credential to upload the image.
for further queries and detail analysis. Visit this official documentation https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-upload-data-blob-storage/

Related

IPFS read data from network

I am working on one application, where I am using IPFS for storing and getting files.
I am using the following API for Android,
https://github.com/ligi/ipfs-api-kotlin
As per the doc, I can get data from IPFS using following code,
ipfs.get.cat("hash code of IPFS file")
but here it returns everything in string format, even if the uploaded file is Image.
How Can I know the content type of the file and download the same format?
IPFS doesn't allow to store metadata such as the content type alongside the content itself.
Something you could do in Java that worked for me:
private static String guessContentType(InputStream content) {
try {
String guessedContentType = URLConnection.guessContentTypeFromStream(content);
if (!StringUtils.isEmpty(guessedContentType)) {
return guessedContentType;
} else {
return MediaType.APPLICATION_OCTET_STREAM_VALUE;
}
} catch (IOException e) {
throw new RuntimeException("Unable to guess content type", e);
}
}

How to make an Android REST client to post videos/images to a Jersey web service?

I have a functional web service in Jersey, that consumes a multi part form data like videos and images and stores them on a directory. I am able to upload videos and images from a browser. Now I want to upload them from an Android application by selecting from gallery Intent or camera.
How am I supposed to do so?
Any help will be appreciated. Here is my web service code.
#Path("/fileupload")
public class UploadFileService {
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public String uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
try {
String uploadedFileLocation = "/home/aamir/Downloads/" + fileDetail.getFileName();
// save it
saveToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded via Jersey based RESTFul Webservice to: " + uploadedFileLocation;
return output;
}
catch(Exception e)
{
return "error";
}
}
// save uploaded file to new location
private void saveToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = null;
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I suggest you use Retrofit to download the image. It's a great library for handling RESTful applications:
Use retrofit to download image file
You can use the Jersey client API in your Android app (or any other client API for that matter, Apache CXF springs to mind...). It lives in a standalone jar which you can add to your app as a dependency, then in your app create a shared client which you use to create requests.
From the Jersey client docs...
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:9998").path("resource");
Form form = new Form();
form.param("x", "foo");
form.param("y", "bar");
MyJAXBBean bean =
target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE),
MyJAXBBean.class);
https://jersey.java.net/documentation/latest/client.html

Android OS - How to track Azure upload progress

I've been working with Azure on the Android OS and I managed to upload my video file (.mp4) to a Container I had already prepared for it.
I did this by getting a Shared Access Signature (SAS) first, which provided me with:
a temporary key
the name of the container to where I want to send the files
the server URI
Then, I started an AsyncTask to send the file to the container using the "upload".
I checked the container, and the file gets uploaded perfectly, no problems on that end.
My question is regarding the progress of the upload. Is it possible to track it? I would like to have an upload bar to give a better UX.
P.S - I'm using the Azure Mobile SDK
Here's my code:
private void uploadFile(String filename){
mFileTransferInProgress = true;
try {
Log.d("Funky Stuff", "Blob Azure Config");
final String gFilename = filename;
File file = new File(filename); // File path
String blobUri = blobServerURL + sharedAccessSignature.replaceAll("\"", "");
StorageUri storage = new StorageUri(URI.create(blobUri));
CloudBlobClient blobCLient = new CloudBlobClient(storage);
//Container name here
CloudBlobContainer container = blobCLient.getContainerReference(blobContainer);
blob = container.getBlockBlobReference(file.getName());
//fileToByteConverter is a method to convert files to a byte[]
byte[] buffer = fileToByteConverter(file);
ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);
if (blob != null) {
new UploadFileToAzure().execute(inputStream);
}
} catch (StorageException e) {
Log.d("Funky Stuff", "StorageException: " + e.toString());
e.printStackTrace();
} catch (IOException e) {
Log.d("Funky Stuff", "IOException: " + e.toString());
e.printStackTrace();
} catch (Exception e) {
Log.d("Funky Stuff", "Exception: " + e.toString());
e.printStackTrace();
}
mFileTransferInProgress = false;
//TODO: Missing ProgressChanged method from AWS
}
private class UploadFileToAzure extends
AsyncTask <ByteArrayInputStream, Void, Void>
{
#Override
protected Void doInBackground(ByteArrayInputStream... params) {
try {
Log.d("Funky Stuff", "Entered UploadFileToAzure Async" + uploadEvent.mFilename);
//Method to upload, takes an InputStream and a size
blob.upload(params[0], params[0].available());
params[0].close();
} catch (StorageException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Thanks!
You can split your file and send its part using Block, there is a good example of your case in this link but it used C# so you should find the corresponding function in the android library reference.
Basically instead of sending you file as one big file, you split it to multiple files (bytes) and send it to azure so you can track the progress on how many bytes that already sent to azure

Dropbox Api AccessToken Changed

I am developing an android application that has the potential to provide large amount of statistical information. I want to save this data on my dropbox to be analyzed later.
So I used the AuthActivity to get the key and secret for my own account, which I then hardcoded to get an AcessTokenPair instance:
AcessTokenPair tokenPair = new AccessTokenPair("key", "secret");
mDBApi.getSession().setAccessTokenPair(tokenPair);
I then send the file to my dropbox using the AsyncTask below:
private class SendToDropbox extends AsyncTask<String, Void, String> {
#SuppressWarnings("deprecation")
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
String timestamp = new Date().toString();
FileInputStream inputStream = null;
DisplayMetrics dm = new DisplayMetrics();
win.getDefaultDisplay().getMetrics(dm);
double x = Math.pow(dm.widthPixels / dm.xdpi, 2);
double y = Math.pow(dm.heightPixels / dm.ydpi, 2);
double screenInches = Math.sqrt(x + y);
File sdcard = new File(Environment.getExternalStorageDirectory()
.getPath());
File session = null;
try {
session = File.createTempFile("analytics_" + timestamp, ".txt", sdcard);
if (session.exists()) {
PrintStream ps = new PrintStream(session);
ps.println("Screen Size: " + screenInches);
ps.println("Device: " + android.os.Build.MODEL);
ps.println("Carrier: " + android.os.Build.BRAND);
ps.println("Locale: " + Locale.getDefault().toString());
ps.println("OS: " + android.os.Build.VERSION.SDK);
ps.println("${EOF}");
ps.checkError();
ps.close();
inputStream = new FileInputStream(session);
com.dropbox.client2.DropboxAPI.Entry newEntry = mDBApi
.putFile("Analytics" + File.separator
+ session.getName(), inputStream,
session.length(), null, null);
if (session.delete()) {
} else {
session.deleteOnExit();
}
Log.i("DbExampleLog", "The uploaded file's rev is: "
+ newEntry.rev);
} else {
Log.e("DropBoxFile", "SD NOT MOUNTED!!");
}
} catch (DropboxUnlinkedException e) {
// User has unlinked, ask them to link again here.
Log.e("DbExampleLog", "User has unlinked.");
} catch (DropboxException e) {
Log.e("DbExampleLog", "Something went wrong while uploading.");
} catch (FileNotFoundException e) {
Log.e("DbExampleLog", "File not found.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
}
}
}
return null;
}
The only problem with this code is that it only works a few weeks, maybe a month before the access token changes. This means I would have to manually update the apk every few weeks, which isn't very feasible. Instead I would like to store the keys on a website or online file that I can access via http.
Are there any free programs that DO NOT require account access and allow you to upload and edit .txt files on the web?
Access tokens do not currently expire, though that may change in future. You'd need to be very careful never to unlink your app from the account used to generate the token, though, since that would invalidate the token which is hard-coded into your app.
I can't recommend this, though, for security reasons. A token embedded into your app can be discovered by someone reverse-engineering the app. And anyone with that token can not only read, but also write to the Dropbox (or App folder) to which the token has access, and by doing so they might screw up the other users of your app.
From the Dropbox Best Practices: Best Practices
Your app should take precautions in case of revoked access. Access tokens may be disabled by the user (from the account page), revoked by Dropbox administrators in cases of abuse, or simply expire over time.
In the case where a token is no longer authorized, the REST API will return an HTTP Error 401 Unauthorized response. The iOS SDK detects 401s for you and will call the sessionDidReceiveAuthorizationFailure: method on the session's delegate to notify you that the authorization was revoked. The Android, Python, Ruby, and Java SDKs will all raise an exception on server errors that you can catch and inspect. Re-authenticating is typically all that is necessary to regain access.
So the Access Token can surely change over time. You just must be flexible enough to deal with that.

How to upload Image and tweet the message without using TweetPic for twitter?

In my application i am using tweetPic to uploaded image but with the image is only able to see on the tweetPic.
Instead of that i want to upload the picture on the twitter and also with the custom message. So how it is possible?
Twitter OAuth is also required for that.
I want any demo or sample example app that done like that.
Thanks.
Well i have search many but still not get the answer as i want.
Finally i use this to upload the photo on Twitter with the Custom Message:
File picture = new File(APP_FILE_PATH + "/"+filename+".jpg");
// Create TwitPic object and allocate TwitPicResponse object
TwitPic tpRequest = new TwitPic(TWITTER_NAME, TWITTER_PASSWORD);
TwitPicResponse tpResponse = null;
// Make request and handle exceptions
try {
tpResponse = tpRequest.uploadAndPost(picture, customMessageEditText.getText()+" http://www.MySite.com/");
}
catch (IOException e) {
e.printStackTrace();
}
catch (TwitPicException e) {
e.printStackTrace();
}
// If we got a response back, print out response variables
if(tpResponse != null) {
tpResponse.dumpVars();
System.out.println(tpResponse.getStatus());
if(tpResponse.getStatus().equals("ok")){
Toast.makeText(getApplicationContext(), "Photo posted on Twitter.",Toast.LENGTH_SHORT).show();
}
}
Still in search of the Twitter Demo to tweet pics on the Twitter with custom message with twitter OAuth and Without using twitPic.
Enjoy. :)
Thanks.

Categories

Resources