Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions cloudinary-core/src/main/scala/com/cloudinary/Uploader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,15 @@ class Uploader(implicit val cloudinary: Cloudinary) {
callApi[UploadResponse]("upload", params.toMap, file, resourceType, params.signed, requestTimeout)
}

def uploadLarge(file: AnyRef, params: LargeUploadParameters = LargeUploadParameters(), resourceType: String = "raw", bufferSize: Int = 20000000) = {
uploadLargeInternal(file, params, resourceType, bufferSize)
}

def uploadLargeRaw(file: AnyRef, params: LargeUploadParameters = LargeUploadParameters(), bufferSize: Int = 20000000) = {
uploadLargeInternal(file, params, "raw", bufferSize)
}

private def uploadLargeInternal(file: AnyRef, params: LargeUploadParameters = LargeUploadParameters(), resourceType: String, bufferSize: Int = 20000000) = {
val (input, fileName) = file match {
case s: String =>
val f = new File(s)
Expand All @@ -99,32 +107,32 @@ class Uploader(implicit val cloudinary: Cloudinary) {
case is: InputStream => (is, None)
}
try {
uploadLargeRawPart(input, params, fileName, bufferSize)
uploadLargePart(input, params, fileName, resourceType, bufferSize)
} catch {
case e: Exception =>
input.close()
throw e
}
}

private def uploadLargeRawPart(input: InputStream, params: LargeUploadParameters, originalFileName: Option[String], bufferSize: Int, partNumber: Int = 1): Future[LargeRawUploadResponse] = {
private def uploadLargePart(input: InputStream, params: LargeUploadParameters, originalFileName: Option[String], resourceType: String = "image", bufferSize: Int, partNumber: Int = 1): Future[LargeRawUploadResponse] = {
val uploadParams = params.toMap + ("part_number" -> partNumber.toString)
val (last, buffer) = readChunck(input, bufferSize)
val part = new ByteArrayPart("file", buffer)
part.setFileName(originalFileName.getOrElse("file"))
(partNumber, last) match {
case (_, true) =>
input.close()
callApi[LargeRawUploadResponse]("upload_large", uploadParams + ("final" -> "1"), part, "raw")
callApi[LargeRawUploadResponse]("upload_large", uploadParams + ("final" -> "1"), part, resourceType)
case (1, _) =>
val responseFuture = callApi[LargeRawUploadResponse]("upload_large", uploadParams, part, "raw")
val responseFuture = callApi[LargeRawUploadResponse]("upload_large", uploadParams, part, resourceType)
responseFuture.flatMap { response =>
uploadLargeRawPart(input, params.publicId(response.public_id).uploadId(response.upload_id.get), originalFileName, bufferSize, partNumber + 1)
uploadLargePart(input, params.publicId(response.public_id).uploadId(response.upload_id.get), originalFileName, resourceType, bufferSize, partNumber + 1)
}
case _ =>
val responseFuture = callApi[LargeRawUploadResponse]("upload_large", uploadParams, part, "raw")
val responseFuture = callApi[LargeRawUploadResponse]("upload_large", uploadParams, part, resourceType)
responseFuture.flatMap {
response => uploadLargeRawPart(input, params, originalFileName, bufferSize, partNumber + 1)
response => uploadLargePart(input, params, originalFileName, resourceType, bufferSize, partNumber + 1)
}
}
}
Expand Down Expand Up @@ -241,10 +249,10 @@ class Uploader(implicit val cloudinary: Cloudinary) {
val cloudinaryUploadUrl = cloudinary.cloudinaryApiUrl("upload", resourceType)

s"""
<input type="file" name="file"
data-url="$cloudinaryUploadUrl"
data-form-data="$tagParams"
data-cloudinary-field="$field"
<input type="file" name="file"
data-url="$cloudinaryUploadUrl"
data-form-data="$tagParams"
data-cloudinary-field="$field"
class="$classes"
$htmlOptionsString/>
"""
Expand Down
Binary file not shown.
29 changes: 20 additions & 9 deletions cloudinary-core/src/test/scala/com/cloudinary/UploaderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class UploaderSpec extends MockableFlatSpec with Matchers with OptionValues with
it should "prevent non whitelisted formats from being uploaded if allowed_formats is specified" in {
Await.result(for {
error <- uploader.upload(s"$testResourcePath/logo.png", options.allowedFormats(Set("jpg"))).recover{case e => e}
} yield {error}, 5.seconds).isInstanceOf[BadRequest] should equal(true)
} yield {error}, 5.seconds).isInstanceOf[BadRequest] should equal(true)
}

it should "allow non whitelisted formats if type is specified and convert to that type" in {
Expand Down Expand Up @@ -266,7 +266,7 @@ class UploaderSpec extends MockableFlatSpec with Matchers with OptionValues with
UploadParameters().callback("http://localhost/cloudinary_cors.html"),
Map("class" -> "myclass")) should include("class=\"cloudinary-fileupload myclass\"")
}

it should "support requesting manual moderation" in {
Await.result(for {
result <- uploader.upload(s"$testResourcePath/logo.png", options.moderation("manual"))
Expand All @@ -275,35 +275,35 @@ class UploaderSpec extends MockableFlatSpec with Matchers with OptionValues with
result.moderation.head.kind should equal("manual")
}, 10.seconds)
}

it should "support requesting raw conversion" in {
val error = Await.result(for {
e <- uploader.upload(s"$testResourcePath/docx.docx", options.rawConvert("illegal"), "raw").recover{case e => e}
} yield e, 10.seconds)
error.asInstanceOf[BadRequest].message should include("not a valid")
}

it should "support requesting categorization" in {
val error = Await.result(for {
e <- uploader.upload(s"$testResourcePath/logo.png", options.categorization("illegal")).recover{case e => e}
} yield e, 10.seconds)
error.asInstanceOf[BadRequest].message should include("is invalid")
}

it should "support requesting detection" in {
val error = Await.result(for {
e <- uploader.upload(s"$testResourcePath/logo.png", options.detection("illegal")).recover{case e => e}
} yield e, 10.seconds)
error.asInstanceOf[BadRequest].message should include("not a valid")
}

it should "support requesting auto_tagging" in {
val error = Await.result(for {
e <- uploader.upload(s"$testResourcePath/logo.png", options.autoTagging(0.5)).recover{case e => e}
} yield e, 10.seconds)
error.asInstanceOf[BadRequest].message should include("Must use")
}

it should "support uploading large raw files" in {
Await.result(for {
response <- uploader.uploadLargeRaw(s"$testResourcePath/docx.docx", LargeUploadParameters().tags(Set("large_upload_test_tag")))
Expand All @@ -314,8 +314,19 @@ class UploaderSpec extends MockableFlatSpec with Matchers with OptionValues with
}, 10.seconds)
}

it should "support uploading large video files" in {
Await.result(for {
response <- uploader.uploadLarge(s"$testResourcePath/rxnvjzsnhjxa4qdqik7i.mp4", LargeUploadParameters().tags(Set("large_upload_test_tag")), "video")
} yield {
response.bytes should equal(new java.io.File(s"$testResourcePath/rxnvjzsnhjxa4qdqik7i.mp4").length())
response.tags should equal(List("large_upload_test_tag"))
response.done should equal(Some(true))
response.resource_type should equal("video")
}, 10.seconds)
}

it should "support unsigned uploading using presets" taggedAs(UploadPresetTest) in {
val c = cloudinary.withConfig(Map("api_key" -> null, "api_secret" -> null))
val c = cloudinary.withConfig(Map("api_key" -> null, "api_secret" -> null))
val (presetName, uploadResult) = Await.result(for {
preset <- api.createUploadPreset(UploadPreset(unsigned = true, settings = options.folder("upload_folder")))
result <- uploader.unsignedUpload(s"$testResourcePath/logo.png", preset.name)
Expand Down Expand Up @@ -351,4 +362,4 @@ class UploaderSpec extends MockableFlatSpec with Matchers with OptionValues with
duration should be < 2000L
}).test
}
}
}