Skip to content
This repository has been archived by the owner on Nov 20, 2018. It is now read-only.

Commit

Permalink
feat(addCanvas): allow addFiles to accept canvas
Browse files Browse the repository at this point in the history
TODO:
- canvas to addFiles unit tests
- manual canvas uploading tests

#1198
  • Loading branch information
Ray Nicholus committed Oct 3, 2014
1 parent b852050 commit ee98f62
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 281 deletions.
2 changes: 1 addition & 1 deletion client/js/image-support/scaler.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ qq.extend(qq.Scaler.prototype, {
var scaledImageDataUri = canvas.toDataURL(type, quality),
signalSuccess = function() {
log("Success generating scaled version for " + sourceFile.name);
var blob = self._dataUriToBlob(scaledImageDataUri);
var blob = qq.dataUriToBlob(scaledImageDataUri);
scalingEffort.success(blob);
};

Expand Down
71 changes: 31 additions & 40 deletions client/js/uploader.basic.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,9 @@
"use strict";

qq.basePublicApi = {
// DEPRECATED - TODO REMOVE IN NEXT MAJOR RELEASE (replaced by addFiles)
addBlobs: function(blobDataOrArray, params, endpoint) {
if (!qq.supportedFeatures.blobUploading) {
throw new qq.Error("Blob uploading is not supported in this browser!");
}

this._maybeHandleIos8SafariWorkaround();

if (blobDataOrArray) {
var blobDataArray = [].concat(blobDataOrArray),
verifiedBlobDataList = [],
batchId = this._storedIds.length === 0 ? qq.getUniqueId() : this._currentBatchId,
self = this;

this._currentBatchId = batchId;

qq.each(blobDataArray, function(idx, blobData) {
var blobOrBlobData;

if (qq.isBlob(blobData) && !qq.isFileOrInput(blobData)) {
blobOrBlobData = {
blob: blobData,
name: self._options.blobs.defaultName
};
}
else if (qq.isObject(blobData) && blobData.blob && blobData.name) {
blobOrBlobData = blobData;
}
else {
self.log("addBlobs: entry at index " + idx + " is not a Blob or a BlobData object", "error");
}

blobOrBlobData && self._handleNewFile(blobOrBlobData, batchId, verifiedBlobDataList);
});

this._prepareItemsForUpload(verifiedBlobDataList, params, endpoint);
}
else {
this.log("undefined or non-array parameter passed into addBlobs", "error");
}
this.addFiles(blobDataOrArray, params, endpoint);
},

addFiles: function(data, params, endpoint) {
Expand All @@ -63,6 +27,25 @@
this._handleNewFile(blobData, batchId, verifiedFiles);
}, this),

processCanvas = qq.bind(function(canvas) {
var blob = qq.canvasToBlob(canvas);

this._handleNewFile({
blob: blob,
name: this._options.blobs.defaultName + ".png"
}, batchId, verifiedFiles);
}, this),

processCanvasData = qq.bind(function(canvasData) {
var normalizedQuality = canvasData.quality && canvasData.quality / 100,
blob = qq.canvasToBlob(canvasData.canvas, canvasData.type, normalizedQuality);

this._handleNewFile({
blob: blob,
name: canvasData.name
}, batchId, verifiedFiles);
}, this),

processFileOrInput = qq.bind(function(fileOrInput) {
if (qq.isInput(fileOrInput) && qq.supportedFeatures.ajaxUploading) {
var files = Array.prototype.slice.call(fileOrInput.files);
Expand Down Expand Up @@ -98,8 +81,16 @@
else if (qq.isBlob(fileContainer)) {
processBlob(fileContainer);
}
else if (qq.isObject(fileContainer) && fileContainer.blob && fileContainer.name) {
processBlobData(fileContainer);
else if (qq.isObject(fileContainer)) {
if (fileContainer.blob && fileContainer.name) {
processBlobData(fileContainer);
}
else if (fileContainer.canvas && fileContainer.name) {
processCanvasData(fileContainer);
}
}
else if (fileContainer.tagName && fileContainer.tagName.toLowerCase() === "canvas") {
processCanvas(fileContainer);
}
else {
self.log(fileContainer + " is not a valid file container! Ignoring!", "warn");
Expand Down
46 changes: 46 additions & 0 deletions client/js/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,52 @@ var qq = function(element) {
(function() {
"use strict";

qq.canvasToBlob = function(canvas, mime, quality) {
return qq.dataUriToBlob(canvas.toDataURL(mime, quality));
};

qq.dataUriToBlob = function(dataUri) {
var arrayBuffer, byteString,
createBlob = function(data, mime) {
var BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder,
blobBuilder = BlobBuilder && new BlobBuilder();

if (blobBuilder) {
blobBuilder.append(data);
return blobBuilder.getBlob(mime);
}
else {
return new Blob([data], {type: mime});
}
},
intArray, mimeString;

// convert base64 to raw binary data held in a string
if (dataUri.split(",")[0].indexOf("base64") >= 0) {
byteString = atob(dataUri.split(",")[1]);
}
else {
byteString = decodeURI(dataUri.split(",")[1]);
}

// extract the MIME
mimeString = dataUri.split(",")[0]
.split(":")[1]
.split(";")[0];

// write the bytes of the binary string to an ArrayBuffer
arrayBuffer = new ArrayBuffer(byteString.length);
intArray = new Uint8Array(arrayBuffer);
qq.each(byteString, function(idx, character) {
intArray[idx] = character.charCodeAt(0);
});

return createBlob(arrayBuffer, mimeString);
};

qq.log = function(message, level) {
if (window.console) {
if (!level || level === "info") {
Expand Down
17 changes: 13 additions & 4 deletions docs/api/methods.jmd
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,28 @@ $(document).ready(function() {
{% endmarkdown %}
{{ api_method("addFiles", "addFiles (files[, params[, endpoint]])", "Submit one or more files to the uploader.

A `BlobData` object:
A `BlobWrapper` object:

| Property | Description |
| -------- | :---------- |
| name | the name of the `Blob` |
| blob | the bytes of the `Blob` object being uploaded | {: .table }
| blob | the bytes of the `Blob` object being uploaded
| name | the name of the `Blob` | {: .table }


A `CanvasWrapper` object:

| Property | Description |
| -------- | :---------- |
| canvas | the `<canvas>` to be converted to a file & then uploaded
| name | the name to assign to the created file |
| quality | 1-100 value indicating the desired quality of the converted file (only for image/jpeg)
| type | MIME type of the file to create from this `<canvas>` | {: .table }
",
[
{
"name": "files",
"type": "Array",
"description": "An array of `File`s, `<input>`s, `FileList`s, `Blob`s, or `BlobData` objects"
"description": "An array of `File`s, `<input>`s, `FileList`s, `Blob`s, `BlobWrapper` objects, `<canvas>`es, or `CanvasData` objects"
},
{
"name": "params",
Expand Down
16 changes: 0 additions & 16 deletions docs/features/upload-files.jmd
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,6 @@ their uploads.
the server-side guidelines for either [traditional](../endpoint_handlers/traditional.html) or [Amazon S3](../endpoint_handlers/amazon-s3.html) upload
endpoints.""", "warn") }}

{{
alert("`addFiles` accepts `File`s, `input` elements, or a collection of any of these types
provdided the collection object contains an (integer) index property for each contained item.")
}}

### `BlobData` objects

`BlobData` objects are just `Blobs` with names. Their properties:

```javascript
var blobData = {
name: /* Blob name goes here */
blob: /* Blob goes here */
}
```

### Successfully Uploading

Upload success will occur when the server's response status is 200 and the
Expand Down
5 changes: 3 additions & 2 deletions test/fineuploader/UploadReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOEx

assertCombinedFileIsVaid(requestParser.getTotalFileSize(), outputFile, requestParser.getUuid());
deletePartitionFiles(dir, requestParser.getUuid());
writeResponse(resp.getWriter(), requestParser.generateError() ? "Generated error" : null, isIframe, false, requestParser, outputFile);
writeResponse(resp.getWriter(), requestParser.generateError() ? "Generated error" : null, isIframe, false, requestParser, null);

}
else if (ServletFileUpload.isMultipartContent(req))
{
Expand Down Expand Up @@ -297,7 +298,7 @@ private void writeResponse(PrintWriter writer, String failureReason, boolean isI


response.addProperty("success", true);
response.addProperty("foo", "bar");
response.addProperty("hi", "ho");
if (file != null)
{
response.addProperty("thumbnailUrl", "/" + file.getPath());
Expand Down
2 changes: 1 addition & 1 deletion test/unit/submit-validate-cancel.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ if (qqtest.canDownloadFileAsBlob) {
qqtest.downloadFileAsBlob(testImgKey, testImgType).then(function(blob) {
blob.foo = "bar";

uploader.addBlobs([
uploader.addFiles([
{blob: blob, name: "name1"},
{blob: blob, name: "name2"}
]);
Expand Down
17 changes: 3 additions & 14 deletions test/unit/workarounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,31 +262,20 @@ describe("browser-specific workarounds", function() {
window.alert = origWindowAlert;
});

it("throws an error and pops up an alert if addFiles or addBlobs is called in iOS 8.0.0 Safari", function(done) {
it("throws an error and pops up an alert if addFiles is called in iOS 8.0.0 Safari", function(done) {
var uploader = new qq.FineUploaderBasic({
element: $fixture[0],
button: $button[0],
multiple: true,
workarounds: {
ios8SafariUploads: true
}
}),
alertCalled = 0;
});

window.alert = function() {
alertCalled++;

if (alertCalled === 2) {
done();
}
done();
};

assert.throws(
function() {
uploader.addBlobs();
}, qq.Error
);

assert.throws(
function() {
uploader.addFiles();
Expand Down
Loading

0 comments on commit ee98f62

Please sign in to comment.