How to show progress bar while uploading files to amazon s3? - amazon-web-services

I am uploading files to Amazon S3 bucket and that is working perfectly fine. Now I want to show the progress while uploading them, I have research everywhere but none of them is working. Below is the code for uploading file to Amazon S3 bucket-
On Spring boot controller-
private static final String UPLOAD_FILE_URL = "/uploadImages.htm";
#RequestMapping(value = UPLOAD_FILE_URL, method = RequestMethod.POST)
public ModelAndView uploadImagesRequest(#RequestParam("file") MultipartFile[] files, #RequestParam("filename") String title, HttpServletRequest request) {
ModelAndView model = new ModelAndView("index");
if(awsUploadImageInterface.uploadImage(filess, title, request)) {
model.addObject("successMsg", "Banner Image Is Added Successfully");
}
return "index";
}
Upload Image Functionality-
#Override
public boolean uploadImage(MultipartFile[] file, String title, HttpServletRequest request) {
boolean result = false;
S3BucketUtility s3client = new S3BucketUtility();
InputStream Is;
String key;
Properties prop = new Properties();
InputStream propstream = getClass().getClassLoader().getResourceAsStream("s3.properties");
try {
prop.load(propstream);
} catch (IOException e) {
System.out.println("Properties File Exception in AWS Connection Class: " + e);
}
try {
for (int j = 0; j < file.length; j++) {
if (file[j].getSize() != 0) {
Is = file[j].getInputStream();
String fileext = FilenameUtils.getExtension(file[j].getOriginalFilename());
AWSCredentials credentials = new BasicAWSCredentials(prop.getProperty("acceskey"), prop.getProperty("scretkey"));
String BucketName = prop.getProperty("bucketName");
key = title.concat(".").concat(fileext);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(Long.valueOf(Is.available()));
metadata.setContentType("image".concat("/").concat(fileext));
s3client.uploadfile(credentials, BucketName, key, Is, metadata);
}
}
}catch (AmazonClientException e) {
return result;
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
Hope anyone can help me how to show the progress as I am unable to do. Thanks in advance.

Related

Downloading a file from AWS S3 bucket via AWS SDK corrupts the file

I'm downloading a file (zip) from a bucket in my aws s3 using a java code & aws sdk.
However, the downloaded file is corrupted.
Downloading the file manually works.
I compared the content of the files and notices that the corrupted file contains kind of uncoded chars
see this:
The code that is used to download is the following:
public boolean downloadFile(String bucketName, String fileNameOnServer, String localFileName )
{
S3Object object =null;
InputStream objectData =null;
try
{
object = s3.getObject(new GetObjectRequest(bucketName, fileNameOnServer));
objectData = object.getObjectContent();
}
catch(Exception e)
{
LoggingService.writeToLog("Error001 downloading file "+bucketName+"/"+fileNameOnServer+" to "+localFileName, e, LogModule.CommonUtils,LogLevel.Error);
return false;
}
try
{
FileWriter fw = new FileWriter(localFileName, true);
BufferedWriter bw = new BufferedWriter(fw);
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(object.getObjectContent()));
String line;
while( (line = reader.readLine() ) !=null)
{
bw.write(line);
bw.newLine();
}
LoggingService.writeToLog("file from "+bucketName+"/"+fileNameOnServer+" "+" downloaded to "+bucketName + " successfully", LogModule.CommonUtils,LogLevel.Info);
return true;
}
catch(IOException e)
{
LoggingService.writeToLog("Error downloading file "+bucketName+"/"+fileNameOnServer+" to "+localFileName, e, LogModule.CommonUtils,LogLevel.Error);
return false;
}
finally
{
objectData.close();
bw.close();
object.close();
}
}
catch(IOException e)
{
LoggingService.writeToLog("Error opening local file "+localFileName+" for writing ", e, LogModule.CommonUtils,LogLevel.Error);
return false;
}
}
The documentation for InputStreamReader includes this:
An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset. The charset that it uses may be specified by name or may be given explicitly, or the platform's default charset may be accepted.
In other words, it attempts to treat the data as text data. For binary data like in a zip file, this will almost assuredly corrupt the data. Instead, if you read and write the bytes directly, you will pass them along without changing them:
package com.exampleapp.app;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
public class App
{
public static void main(String[] args)
{
downloadFile("example-bucket", "example-key.zip", "local-file.zip");
}
static AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
public static boolean downloadFile(String bucketName, String fileNameOnServer, String localFileName )
{
S3Object object = null;
InputStream objectData = null;
InputStream reader = null;
OutputStream writer = null;
try
{
object = s3.getObject(new GetObjectRequest(bucketName, fileNameOnServer));
objectData = object.getObjectContent();
}
catch(Exception e)
{
System.out.println("Error001 downloading file "+bucketName+"/"+fileNameOnServer+" to "+localFileName);
return false;
}
try
{
File file = new File(localFileName);
try
{
reader = new BufferedInputStream(object.getObjectContent());
writer = new BufferedOutputStream(new FileOutputStream(file));
int read = -1;
while ( ( read = reader.read() ) != -1 )
{
writer.write(read);
}
System.out.println("file from "+bucketName+"/"+fileNameOnServer+" "+" downloaded to "+bucketName + " successfully");
return true;
}
catch(IOException e)
{
System.out.println("Error downloading file "+bucketName+"/"+fileNameOnServer+" to "+localFileName);
return false;
}
finally
{
object.close();
writer.flush();
writer.close();
reader.close();
}
}
catch(IOException e)
{
System.out.println("Error opening local file "+localFileName+" for writing ");
return false;
}
}
}
The Photo Spring BOOT app now supports downloading an image. It works perfectly. You should use the AWS SDK for Java V2. Here is the example app:
When i open the downloaded image - it is valid and not corrupt:
The code to download this image from an Amazon S3 bucket is located in a Spring Controller:
#RequestMapping(value = "/downloadphoto", method = RequestMethod.GET)
void buildDynamicReportDownload(HttpServletRequest request, HttpServletResponse response) {
try {
//Get the photo object name
String photoKey = request.getParameter("photoKey");
byte[] photoBytes = s3Client.getObjectBytes("myphotobucket", photoKey) ;
InputStream is = new ByteArrayInputStream(photoBytes);
//define the required information to download the image
response.setContentType("image/png");
response.setHeader("Content-disposition", "attachment; filename="+photoKey);
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
} catch (Exception e) {
e.printStackTrace();
}
}
The V2 S3 code is here. Notice it reads an object and returns a byte[].
public byte[] getObjectBytes (String bucketName, String keyName) {
s3 = getClient();
try {
// create a GetObjectRequest instance
GetObjectRequest objectRequest = GetObjectRequest
.builder()
.key(keyName)
.bucket(bucketName)
.build();
// get the byte[] from this AWS S3 object
ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest);
byte[] data = objectBytes.asByteArray();
return data;
} catch (S3Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
return null;
}
Finally the Javascript call
function DownloadImage(){
//Post the values to the controller
var photo = $('#photo').val();
window.location="../downloadphoto?photoKey=" + photo ;
}
This example will be updated so all of this code is in the example doc.
https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/usecases/creating_photo_analyzer_app

com.amazonaws.SdkClientException: Unable to calculate MD5 hash: /home/bharath/Documents/demo/demo.txt (No such file or directory)

By taking the reference of this Question link below
How to solve 'Client is immutable when created with the builder'?
I do have a similar code structure wherein which am getting an error saying
Unable to calculate MD5 hash
public class LambdaFunctionS3 implements RequestHandler<Object, String> {
#Override
public String handleRequest(Object input, Context context) {
context.getLogger().log("Input: " + input);
String clientRegion = "ap-south-1";
String bucketName = "Bucket Name";
String fileObjKeyName = "demo.txt";
String fileName = "/home/bharath/Documents/demo/demo.txt";
try {
System.out.println("Uploading a new file to s3 bucket...");
File file = new File(fileName);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withCredentials(new ProfileCredentialsProvider())
.build();
PutObjectRequest request = new PutObjectRequest(bucketName, fileObjKeyName,file);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType("plain/text");
metadata.addUserMetadata("x-amz-meta-title", "myFunction");
request.setMetadata(metadata);
s3Client.putObject(request);
System.out.println("File uploaded.");
return "Success";
} catch(AmazonServiceException e) {
System.err.println(e.getErrorMessage());
System.exit(1);
e.printStackTrace();
} catch(SdkClientException e) {
e.printStackTrace();
}
return "Hello from Lambda!"; }
Though I have a file with the correct path. Am using aws lambda function in order to upload a file in s3.
Any help?

Amazon Elasticsearch service 403-forbidden error

I am having trouble fetching result from my amazon elastic search cluster using the amazon java SDK and an IAm user credential. Now the issue is that when the PATH string is equal to "/" then I am able to fetch the result correctly but when I try with a different path for e.g "/private-search" then I get a 403 forbidden error. Even when for the path that has public access I am getting a 403 forbidden error for this IAm user but it works if I remove "signer.sign(requestToSign, credentials);" line in performSigningSteps method(for public resource only).
My policy in AWS gives this IAM user access to everything in my elastic search service. And also what can I do to avoid hard-coding the access key and secret key in source code?
private static final String SERVICE_NAME = "es";
private static final String REGION = "region-name";
private static final String HOST = "host-name";
private static final String ENDPOINT_ROOT = "http://" + HOST;
private static final String PATH = "/private-search";
private static final String ENDPOINT = ENDPOINT_ROOT + PATH;
private static String accessKey = "IAmUserAccesskey"
private static String secretKey = "IAmUserSecretkey"
public static void main(String[] args) {
// Generate the request
Request<?> request = generateRequest();
// Perform Signature Version 4 signing
performSigningSteps(request);
// Send the request to the server
sendRequest(request);
}
private static Request<?> generateRequest() {
Request<?> request = new DefaultRequest<Void>(SERVICE_NAME);
request.setContent(new ByteArrayInputStream("".getBytes()));
request.setEndpoint(URI.create(ENDPOINT));
request.setHttpMethod(HttpMethodName.GET);
return request;
}
private static void performSigningSteps(Request<?> requestToSign) {
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(requestToSign.getServiceName());
signer.setRegionName(REGION);
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
signer.sign(requestToSign, credentials);
}
private static void sendRequest(Request<?> request) {
ExecutionContext context = new ExecutionContext();
ClientConfiguration clientConfiguration = new ClientConfiguration();
AmazonHttpClient client = new AmazonHttpClient(clientConfiguration);
MyHttpResponseHandler<Void> responseHandler = new MyHttpResponseHandler<Void>();
MyErrorHandler errorHandler = new MyErrorHandler();
Void response = client.execute(request, responseHandler, errorHandler, context);
}
public static class MyHttpResponseHandler<T> implements HttpResponseHandler<AmazonWebServiceResponse<T>> {
#Override
public AmazonWebServiceResponse<T> handle(com.amazonaws.http.HttpResponse response) throws Exception {
InputStream responseStream = response.getContent();
String responseString = convertStreamToString(responseStream);
System.out.println(responseString);
AmazonWebServiceResponse<T> awsResponse = new AmazonWebServiceResponse<T>();
return awsResponse;
}
#Override
public boolean needsConnectionLeftOpen() {
return false;
}
}
public static class MyErrorHandler implements HttpResponseHandler<AmazonServiceException> {
#Override
public AmazonServiceException handle(com.amazonaws.http.HttpResponse response) throws Exception {
System.out.println("In exception handler!");
AmazonServiceException ase = new AmazonServiceException("exception.");
ase.setStatusCode(response.getStatusCode());
ase.setErrorCode(response.getStatusText());
return ase;
}
#Override
public boolean needsConnectionLeftOpen() {
return false;
}
}
public static String convertStreamToString(InputStream is) throws IOException {
// To convert the InputStream to String we use the
// Reader.read(char[] buffer) method. We iterate until the
// Reader return -1 which means there's no more data to
// read. We use the StringWriter class to produce the string.
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
}
finally {
is.close();
}
return writer.toString();
}
return "";
}

Cannot genetrate java client for file upload webservice

I have a simple file upload web service as a small part of my project.
This is what I have done so far on the server side :
#POST
#Path("/file")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(List<Attachment> attachments,#Context HttpServletRequest request) {
System.out.println("Got an attachment!");
for(Attachment attr : attachments) {
DataHandler handler = attr.getDataHandler();
try {
InputStream stream = handler.getInputStream();
MultivaluedMap map = attr.getHeaders();
OutputStream out = new FileOutputStream(new File("/home/yashdosi/s/" + getFileName(map))); //getFileName is a seperate private function..
int read = 0;
byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
stream.close();
out.flush();
out.close();
} catch(Exception e) {
e.printStackTrace();
}
}
return Response.ok("file uploaded").build();
}
It works perfectly well when requests come from html forms...when I try to send a request from a java client it simply doesnt work..!!
Any ideas about on creating a java client for this code..
Here is the code I tried with...maybe there is a simple error in this code but..I dont see it...also as I said this code simple wont work...no errors or anything else....when I tried printing something on the server console to see if the service is invoked...it did NOT print anything..so I think I am unable to contact the service for some reason...
public static void uploadPhoto()
{
String url = "http://localhost:8080/fileupload-ws/services/postdata";
String output = null;
PostMethod mPost = new PostMethod(url);
HttpClient client = new HttpClient();
try
{
File imageFile = new File("/home/yashdosi/1.jpg");
BufferedImage image = ImageIO.read(imageFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
byte[] encodedImage = Base64.encodeBase64(baos.toByteArray());
String data = " " + " " + "" + "image/jpeg" + " " + "" + new String(encodedImage) + " " + "";
mPost.setRequestBody(data);
mPost.setRequestHeader("Content-Type", "text/xml");
client.executeMethod( mPost );
output = mPost.getResponseBodyAsString( );
mPost.releaseConnection( );
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(output);
}
Finally got a client working!!
HttpClient httpclient = new DefaultHttpClient();
try {
HttpPost httppost = new HttpPost("http://localhost:8080/fileupload-ws/services/postdata");
FileBody img = new FileBody(new File("/home/yashdosi/1.jpg"));
FileBody html = new FileBody(new File("/home/yashdosi/hotmail.html"));
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("image", img);
reqEntity.addPart("html", html);
httppost.setEntity(reqEntity);
httppost.setHeader("Content-Type", "multipart/form-data");
System.out.println("executing request " + httppost.getRequestLine());
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
}
catch(Exception e)
{
e.printStackTrace();
}
finally {
try { httpclient.getConnectionManager().shutdown(); } catch (Exception ignore) {}
}

uploading file from backberry to web service = JVM error 104 Uncaught NullPointerException?

I am developing a small blackberry project.
Here are the step that it is supposed to be:
User clicks Speak! button. The application record speech voice. [No Problem]
When user finishes speaking, click Stop! button. Once the stop button is clicked, the speech voice will be saved on BB as an AMR file. Then, the file will be sent to web service via ksoap2. Web service will return response as a string of file name. The problem is web service return nothing and there is an error occur: JVM error 104: Uncaught NullPointerException I wonder if I placed the code on the right place, or I did something wrong with ksoap2??
here is the code for web service
namespace VoiceServer
{
/// <summary>
/// Converting AMR to WAV
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
public string UploadFile(String receivedByte, String location, String fileName)
{
String filepath = fileName;
/*don't worry about receivedByte and location, I will work on them after the problem is solved :) */
return "Success"+filepath;
}
private void InitializeComponent()
{
}
}
}
Below is the code running on Eclipse, I'm not sure if I placed the code for sending file to web service on the right place.
public class MyAudio extends MainScreen {
private ButtonField _startRecordingButton;
private ButtonField _stopRecordingButton;
private HorizontalFieldManager _fieldManagerButtons;
private VoiceNotesRecorderThread _voiceRecorder;
private LabelField _myAudioTextField;
private DateField hourMin;
private long _initTime;
public MyAudio() {
_startRecordingButton = new ButtonField("Speak!", ButtonField.CONSUME_CLICK);
_stopRecordingButton = new ButtonField("Stop!", ButtonField.CONSUME_CLICK);
_fieldManagerButtons = new HorizontalFieldManager();
_voiceRecorder = new VoiceNotesRecorderThread(500000,"file:///store/home/user/voicefile.amr",this);
_voiceRecorder.start();
myButtonFieldChangeListener buttonFieldChangeListener = new myButtonFieldChangeListener();
_startRecordingButton.setChangeListener(buttonFieldChangeListener);
_stopRecordingButton.setChangeListener(buttonFieldChangeListener);
_fieldManagerButtons.add(_startRecordingButton);
_fieldManagerButtons.add(_stopRecordingButton);
_myAudioTextField = new LabelField(" Welcome to VoiceSMS!!!" );
add(_fieldManagerButtons);
add(_myAudioTextField);
SimpleDateFormat sdF = new SimpleDateFormat("ss");
hourMin = new DateField("", 0, sdF);
hourMin.setEditable(false);
hourMin.select(false);
_initTime = System.currentTimeMillis();
add(hourMin);
}
public void setAudioTextField(String text) {
_myAudioTextField.setText(text);
}
public void startTime() {
_initTime = System.currentTimeMillis();
hourMin.setDate(0);
}
public void updateTime() {
hourMin.setDate((System.currentTimeMillis()-_initTime));
}
class myButtonFieldChangeListener implements FieldChangeListener{
public void fieldChanged(Field field, int context) {
if(field == _startRecordingButton) {
try {
_voiceRecorder.startRecording();
} catch (IOException e) {
e.printStackTrace();
}
}else if(field == _stopRecordingButton) {
_voiceRecorder.stopRecording();
//----------Send AMR to Web Service-------------//
Object response = null;
String URL = "http://http://localhost:portnumber/Service1.asmx";
String method = "UploadFile";
String NameSpace = "http://tempuri.org/";
FileConnection fc = null;
byte [] ary = null;
try
{
fc = (FileConnection)Connector.open("file:///store/home/user/voicefile.amr",Connector.READ_WRITE);
int size = (int) fc.fileSize();
//String a = Integer.toString(size);
//Dialog.alert(a);
ary = new byte[size];
fc.openDataInputStream().read(ary);
fc.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
SoapObject client = new SoapObject(NameSpace,method);
client.addProperty("receivedByte",new SoapPrimitive(SoapEnvelope.ENC,"base64",Base64.encode(ary)));
client.addProperty("location","Test/");
client.addProperty("fileName","file:///store/home/user/voicefile.amr");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = client;
HttpTransport http = new HttpTransport(URL);
try
{
http.call(method,envelope);
}
catch(InterruptedIOException io)
{
io.printStackTrace();
}
catch (IOException e)
{
System.err.println(e);
}
catch (XmlPullParserException e)
{
System.err.println(e);
}
catch(OutOfMemoryError e)
{
System.out.println(e.getMessage());
}
catch(Exception e)
{
e.printStackTrace();
}
try
{
response = envelope.getResponse();
Dialog.alert(response.toString());
}
catch (SoapFault e)
{
System.err.println(e);
System.out.println("Soap Fault");
}
catch(NullPointerException ne)
{
System.err.println(ne);
}
Dialog.alert(response.toString());
//Dialog.alert("Send Success");
//----------End of Upload-to-Web-Service--------//
}
}
}
}
I don't know if the file is not sent to web service, or web service has got the file and produce no response??? I am a real newbie for BB programming. Please let me know if I did anything wrong.
Thanks in advance!!!
There is a typo in your URL variable value.
"http://" typed twice
String URL = "http://http://localhost:portnumber/Service1.asmx";
Hooray!!! Problem Solved!
just changed URL as Rafael suggested and added [WebMethod] above "public string UploadFile" in the web service code