i'm trying to store the images in AWS S3 to serve them as static content in future.
I use Spring MVC, Spring Cloud AWS, AngularJS.
Have a strange issue with File upload to Amazon S3 bucket. uploading a File is very fast
2016-07-17 12:43:11,927 INFO [http-apr-8080-exec-8] impl.S3FileServiceImpl (S3FileServiceImpl.java:39) - Upload started
2016-07-17 12:43:17,061 INFO [http-apr-8080-exec-8] impl.S3FileServiceImpl (S3FileServiceImpl.java:46) - Upload done
But uploading image from MultipartFile received by Spring Servlet takes significantly more. Especially if File name is not in english.(no matter the size)
2016-07-17 12:53:50,715 INFO [http-apr-8080-exec-9] impl.S3FileServiceImpl (S3FileServiceImpl.java:56) - Upload started
2016-07-17 12:54:16,897 INFO [http-apr-8080-exec-9] impl.S3FileServiceImpl (S3FileServiceImpl.java:70) - Upload done
(here it took 26 seconds).
This is the service class i'm trying to make:
public class S3FileServiceImpl implements S3FileService {
private final static Logger logger = LogManager.getLogger(S3FileServiceImpl.class.getName());
@Autowired
private AmazonS3 amazonS3;
private final String bucketName = "bucket1";
public S3FileServiceImpl() {
if(amazonS3 != null) {
logger.info("not null");
if (!amazonS3.doesBucketExist(bucketName)) {
amazonS3.createBucket(bucketName);
}
}
}
@Override
public void uploadFile(String filePath, String fileName, File file) {
logger.info("Upload Started");
TransferManager transferManager = new TransferManager(this.amazonS3);
Upload upload = transferManager.upload(bucketName,filePath +"/"+fileName, file);
try {
upload.waitForUploadResult();
logger.info("Upload done");
transferManager.shutdownNow(false);
} catch (Exception e) {
logger.error("error on file upload to S3: "+e.getMessage());
}
}
@Override
public void uploadFile(String filePath, String fileName, InputStream inputStream, long inputStreamSize, String contentType) {
logger.info("Upload Started");
TransferManager transferManager = new TransferManager(this.amazonS3);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setExpirationTime(DateTime.now().plusDays(365*3).toDate());
metadata.setContentLength(inputStreamSize);
metadata.setContentType(contentType);
Upload upload = transferManager.upload(bucketName,filePath +"/"+fileName, inputStream, metadata);
try {
upload.waitForUploadResult();
inputStream.close();
logger.info("Upload done");
transferManager.shutdownNow(false);
} catch (Exception e) {
logger.error("error on file upload to S3: "+e.getMessage());
}
}
}
This is the controller from which i transfer a MultipartFile:
@RequestMapping(value="/upload_image", method=RequestMethod.POST)
public @ResponseBody JsonResponse handleFileUpload(@RequestParam("file") MultipartFile file, @RequestParam("filename") String filename){
if (!file.isEmpty()) {
try {
String orgName = file.getOriginalFilename();
String filePath = "img_temp";
logger.info("File name: "+orgName);
//Format check
if(!IsImage(orgName)) {retu new JsonResponse("FAIL","Is not an image: "+orgName);}
//Upload
s3FileService.uploadFile(filePath, orgName, file.getInputStream(), file.getSize(), file.getContentType());
//Success
retu new JsonResponse("OK","");
} catch (Exception e) {
retu new JsonResponse("FAIL","File uploaded failed: "+file.getName() + " => " + e.getMessage());
}
} else {
retu new JsonResponse("FAIL","File uploaded failed: "+ file.getName() + " because the file was empty.");
}
}
Main quiestion: Why is it so much slower from MutipartFile (input stream + metadata) ?
Also, by the way - there is a strange issue. In my IDE (Intellij 15.0.3) it shows this error: "No beans of 'AmazonS3' type found." in S3FileServiceImpl class. But still, it is found and working. This is the XML config:
<aws-context:context-region region="us-west-2"/>
<aws-context:context-credentials>
<aws-context:instance-profile-credentials/>
<aws-context:simple-credentials access-key="key" secret-key="key"/>
</aws-context:context-credentials>
<aws-context:context-resource-loader task-executor="executor" />
<task:executor id="executor" pool-size="10" queue-capacity="0" rejection-policy="CALLER_RUNS" />
<bean id="s3FileService" class="com.springapp.mvc.service.impl.S3FileServiceImpl"></bean>
