From 711b2aa859a59dd8aac77e677fa95b642e4fc34d Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 13 Jan 2017 19:15:56 -0800 Subject: [PATCH] api: Regression contentType set by user was never set properly. (#511) The reason is because contentType is overriden by this operation even if the contentType is set through header. ``` public MediaType contentType() { if (contentType != null && !contentType.isEmpty()) { return MediaType.parse(contentType); } else { return MediaType.parse("application/octet-stream"); } } ``` --- api/src/main/java/io/minio/MinioClient.java | 101 +++++++++++++++----- functional/FunctionalTest.java | 18 ++++ 2 files changed, 93 insertions(+), 26 deletions(-) diff --git a/api/src/main/java/io/minio/MinioClient.java b/api/src/main/java/io/minio/MinioClient.java index 95f409896..d16476185 100644 --- a/api/src/main/java/io/minio/MinioClient.java +++ b/api/src/main/java/io/minio/MinioClient.java @@ -664,11 +664,16 @@ private Request createRequest(Method method, String bucketName, String objectNam requestBody = new RequestBody() { @Override public MediaType contentType() { + MediaType mediaType = null; + if (contentType != null) { - return MediaType.parse(contentType); - } else { - return MediaType.parse("application/octet-stream"); + mediaType = MediaType.parse(contentType); } + if (mediaType == null) { + mediaType = MediaType.parse("application/octet-stream"); + } + + return mediaType; } @Override @@ -782,10 +787,15 @@ public void writeTo(BufferedSink sink) throws IOException { */ private HttpResponse execute(Method method, String region, String bucketName, String objectName, Map headerMap, Map queryParamMap, - String contentType, Object body, int length) + Object body, int length) throws InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, InternalException { + String contentType = null; + if (headerMap != null) { + contentType = headerMap.get("Content-Type"); + } + Request request = createRequest(method, bucketName, objectName, region, headerMap, queryParamMap, contentType, body, length); @@ -919,7 +929,7 @@ private void updateRegionCache(String bucketName) queryParamMap.put("location", null); HttpResponse response = execute(Method.GET, US_EAST_1, bucketName, null, - null, queryParamMap, null, null, 0); + null, queryParamMap, null, 0); // existing XmlEntity does not work, so fallback to regular parsing. XmlPullParser xpp = xmlPullParserFactory.newPullParser(); @@ -983,7 +993,7 @@ private HttpResponse executeGet(String bucketName, String objectName, Map headerMap = new HashMap<>(); - String configString; if (region == null || US_EAST_1.equals(region)) { // for 'us-east-1', location constraint is not required. for more info @@ -1938,7 +1946,7 @@ public void makeBucket(String bucketName, String region) configString = config.toString(); } - executePut(bucketName, null, headerMap, null, US_EAST_1, configString, 0); + executePut(bucketName, null, null, null, US_EAST_1, configString, 0); } @@ -1989,6 +1997,7 @@ public void removeBucket(String bucketName) * @param bucketName Bucket name. * @param objectName Object name to create in the bucket. * @param fileName File name to upload. + * @param contentType File content type of the object, user supplied. * * @throws InvalidBucketNameException upon invalid bucket name is given * @throws NoResponseException upon no response from server @@ -1997,7 +2006,7 @@ public void removeBucket(String bucketName) * @throws ErrorResponseException upon unsuccessful execution * @throws InternalException upon internal library error */ - public void putObject(String bucketName, String objectName, String fileName) + public void putObject(String bucketName, String objectName, String fileName, String contentType) throws InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, InternalException, @@ -2011,7 +2020,10 @@ public void putObject(String bucketName, String objectName, String fileName) throw new InvalidArgumentException("'" + fileName + "': not a regular file"); } - String contentType = Files.probeContentType(filePath); + if (contentType == null) { + contentType = Files.probeContentType(filePath); + } + long size = Files.size(filePath); RandomAccessFile file = new RandomAccessFile(filePath.toFile(), "r"); @@ -2022,6 +2034,40 @@ public void putObject(String bucketName, String objectName, String fileName) } } + /** + * Uploads given file as object in given bucket. + *

+ * If the object is larger than 5MB, the client will automatically use a multipart session. + *

+ *

+ * If the session fails, the user may attempt to re-upload the object by attempting to create + * the exact same object again. The client will examine all parts of any current upload session + * and attempt to reuse the session automatically. If a mismatch is discovered, the upload will fail + * before uploading any more data. Otherwise, it will resume uploading where the session left off. + *

+ *

+ * If the multipart session fails, the user is responsible for resuming or removing the session. + *

+ * + * @param bucketName Bucket name. + * @param objectName Object name to create in the bucket. + * @param fileName File name to upload. + * + * @throws InvalidBucketNameException upon invalid bucket name is given + * @throws NoResponseException upon no response from server + * @throws IOException upon connection error + * @throws XmlPullParserException upon parsing response xml + * @throws ErrorResponseException upon unsuccessful execution + * @throws InternalException upon internal library error + */ + public void putObject(String bucketName, String objectName, String fileName) + throws InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, IOException, + InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, + InternalException, + InvalidArgumentException, InsufficientDataException { + putObject(bucketName, objectName, fileName, null); + } + /** * Uploads data from given stream as object to given bucket. @@ -2103,20 +2149,21 @@ private String putObject(String bucketName, String objectName, int length, throws InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, InternalException { + Map headerMap = new HashMap<>(); + if (contentType != null && !contentType.isEmpty()) { + headerMap.put("Content-Type", contentType); + } else { + headerMap.put("Content-Type", "application/octet-stream"); + } + Map queryParamMap = null; if (partNumber > 0 && uploadId != null && !"".equals(uploadId)) { queryParamMap = new HashMap<>(); queryParamMap.put("partNumber", Integer.toString(partNumber)); queryParamMap.put(UPLOAD_ID, uploadId); } - Map headerMap = new HashMap<>(); - if (contentType != null) { - headerMap.put("Content-Type", contentType); - } else { - headerMap.put("Content-Type", "application/octet-stream"); - } - HttpResponse response = executePut(bucketName, objectName, headerMap, - queryParamMap, data, length); + + HttpResponse response = executePut(bucketName, objectName, headerMap, queryParamMap, data, length); return response.header().etag(); } @@ -2252,13 +2299,15 @@ private void setBucketPolicy(String bucketName, BucketPolicy policy) throws InvalidBucketNameException, InvalidObjectPrefixException, NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, InternalException { + Map headerMap = new HashMap<>(); + headerMap.put("Content-Type", "application/json"); + Map queryParamMap = new HashMap<>(); queryParamMap.put("policy", ""); String policyJson = policy.getJson(); - HttpResponse response = executePut(bucketName, "", null, queryParamMap, policyJson, policyJson.length()); - response.body().close(); + executePut(bucketName, null, headerMap, queryParamMap, policyJson, policyJson.length()); } @@ -2565,7 +2614,7 @@ private String initMultipartUpload(String bucketName, String objectName, String InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, InternalException { Map headerMap = new HashMap<>(); - if (contentType != null) { + if (contentType != null && !contentType.isEmpty()) { headerMap.put("Content-Type", contentType); } else { headerMap.put("Content-Type", "application/octet-stream"); diff --git a/functional/FunctionalTest.java b/functional/FunctionalTest.java index 04ff6d1e9..aaa81be37 100644 --- a/functional/FunctionalTest.java +++ b/functional/FunctionalTest.java @@ -214,6 +214,23 @@ public static void putObject_test4() throws Exception { client.removeObject(bucketName, fileName); } + /** + * Test: multipart: putObject(String bucketName, String objectName, String fileName, String contentType). + */ + public static void putObject_test5() throws Exception { + System.out.println("Test: multipart: putObject(String bucketName, String objectName, String fileName," + + " String contentType)"); + String fileName = createFile(13 * MB); + client.putObject(bucketName, fileName, fileName, customContenType); + Files.delete(Paths.get(fileName)); + ObjectStat objectStat = client.statObject(bucketName, fileName); + if (!customContenType.equals(objectStat.contentType())) { + throw new Exception("[FAILED] Test: putObject(String bucketName, String objectName, String fileName," + + " String contentType)"); + } + client.removeObject(bucketName, fileName); + } + /** * Test: statObject(String bucketName, String objectName). */ @@ -858,6 +875,7 @@ public static void main(String[] args) { putObject_test2(); putObject_test3(); putObject_test4(); + putObject_test5(); statObject_test();