mirror of
https://github.com/apache/cordova-plugin-file-transfer.git
synced 2024-10-06 07:42:20 +08:00
CB-9837 Add data URI support to file-transfer upload on iOS
Adds iOS and Windows implementation; mention in the docs Adds corresponding tests Increases spec.35 timeout for Windows Phone 8.1 case as it contains 2 download operations
This commit is contained in:
parent
a9470ff1cc
commit
182b0c5ebe
@ -74,7 +74,7 @@ multi-part POST or PUT request, and to download files as well.
|
||||
|
||||
__Parameters__:
|
||||
|
||||
- __fileURL__: Filesystem URL representing the file on the device. For backwards compatibility, this can also be the full path of the file on the device. (See [Backwards Compatibility Notes] below)
|
||||
- __fileURL__: Filesystem URL representing the file on the device or a [data: URI](https://en.wikipedia.org/wiki/Data_URI_scheme). For backwards compatibility, this can also be the full path of the file on the device. (See [Backwards Compatibility Notes](#backwards-compatibility-notes) below)
|
||||
|
||||
- __server__: URL of the server to receive the file, as encoded by `encodeURI()`.
|
||||
|
||||
|
@ -244,6 +244,11 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
|
||||
int numChunks = sizeof(chunks) / sizeof(chunks[0]);
|
||||
|
||||
for (int i = 0; i < numChunks; ++i) {
|
||||
// Allow uploading of an empty file
|
||||
if (chunks[i].length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CFIndex result = WriteDataToStream(chunks[i], writeStream);
|
||||
if (result <= 0) {
|
||||
break;
|
||||
@ -297,6 +302,28 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
|
||||
NSString* server = [command argumentAtIndex:1];
|
||||
NSError* __autoreleasing err = nil;
|
||||
|
||||
if ([source hasPrefix:@"data:"] && [source rangeOfString:@"base64"].location != NSNotFound) {
|
||||
NSRange commaRange = [source rangeOfString: @","];
|
||||
if (commaRange.location == NSNotFound) {
|
||||
// Return error is there is no comma
|
||||
__weak CDVFileTransfer* weakSelf = self;
|
||||
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[weakSelf createFileTransferError:INVALID_URL_ERR AndSource:source AndTarget:server]];
|
||||
[weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
if (commaRange.location + 1 > source.length - 1) {
|
||||
// Init as an empty data
|
||||
NSData *fileData = [[NSData alloc] init];
|
||||
[self uploadData:fileData command:command];
|
||||
return;
|
||||
}
|
||||
|
||||
NSData *fileData = [[NSData alloc] initWithBase64EncodedString:[source substringFromIndex:(commaRange.location + 1)] options:NSDataBase64DecodingIgnoreUnknownCharacters];
|
||||
[self uploadData:fileData command:command];
|
||||
return;
|
||||
}
|
||||
|
||||
CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:source];
|
||||
NSObject<CDVFileSystem> *fs;
|
||||
if (sourceURL) {
|
||||
|
@ -31,6 +31,9 @@ var FTErr = require('./FileTransferError'),
|
||||
|
||||
var appData = Windows.Storage.ApplicationData.current;
|
||||
|
||||
var LINE_START = "--";
|
||||
var LINE_END = "\r\n";
|
||||
var BOUNDARY = '+++++';
|
||||
|
||||
// Some private helper functions, hidden by the module
|
||||
function cordovaPathToNative(path) {
|
||||
@ -54,6 +57,93 @@ function alreadyCancelled(opId) {
|
||||
return op && op.state === FileTransferOperation.CANCELLED;
|
||||
}
|
||||
|
||||
function doUpload (upload, uploadId, filePath, server, successCallback, errorCallback) {
|
||||
if (alreadyCancelled(uploadId)) {
|
||||
errorCallback(new FTErr(FTErr.ABORT_ERR, nativePathToCordova(filePath), server));
|
||||
return;
|
||||
}
|
||||
|
||||
// update internal TransferOperation object with newly created promise
|
||||
var uploadOperation = upload.startAsync();
|
||||
fileTransferOps[uploadId].promise = uploadOperation;
|
||||
|
||||
uploadOperation.then(
|
||||
function (result) {
|
||||
// Update TransferOperation object with new state, delete promise property
|
||||
// since it is not actual anymore
|
||||
var currentUploadOp = fileTransferOps[uploadId];
|
||||
if (currentUploadOp) {
|
||||
currentUploadOp.state = FileTransferOperation.DONE;
|
||||
currentUploadOp.promise = null;
|
||||
}
|
||||
|
||||
var response = result.getResponseInformation();
|
||||
var ftResult = new FileUploadResult(result.progress.bytesSent, response.statusCode, '');
|
||||
|
||||
// if server's response doesn't contain any data, then resolve operation now
|
||||
if (result.progress.bytesReceived === 0) {
|
||||
successCallback(ftResult);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise create a data reader, attached to response stream to get server's response
|
||||
var reader = new Windows.Storage.Streams.DataReader(result.getResultStreamAt(0));
|
||||
reader.loadAsync(result.progress.bytesReceived).then(function (size) {
|
||||
ftResult.response = reader.readString(size);
|
||||
successCallback(ftResult);
|
||||
reader.close();
|
||||
});
|
||||
},
|
||||
function (error) {
|
||||
var source = nativePathToCordova(filePath);
|
||||
|
||||
// Handle download error here.
|
||||
// Wrap this routines into promise due to some async methods
|
||||
var getTransferError = new WinJS.Promise(function (resolve) {
|
||||
if (error.message === 'Canceled') {
|
||||
// If download was cancelled, message property will be specified
|
||||
resolve(new FTErr(FTErr.ABORT_ERR, source, server, null, null, error));
|
||||
} else {
|
||||
// in the other way, try to get response property
|
||||
var response = upload.getResponseInformation();
|
||||
if (!response) {
|
||||
resolve(new FTErr(FTErr.CONNECTION_ERR, source, server));
|
||||
} else {
|
||||
var reader = new Windows.Storage.Streams.DataReader(upload.getResultStreamAt(0));
|
||||
reader.loadAsync(upload.progress.bytesReceived).then(function (size) {
|
||||
var responseText = reader.readString(size);
|
||||
resolve(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, server, response.statusCode, responseText, error));
|
||||
reader.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Update TransferOperation object with new state, delete promise property
|
||||
// since it is not actual anymore
|
||||
var currentUploadOp = fileTransferOps[uploadId];
|
||||
if (currentUploadOp) {
|
||||
currentUploadOp.state = FileTransferOperation.CANCELLED;
|
||||
currentUploadOp.promise = null;
|
||||
}
|
||||
|
||||
// Report the upload error back
|
||||
getTransferError.then(function (transferError) {
|
||||
errorCallback(transferError);
|
||||
});
|
||||
},
|
||||
function (evt) {
|
||||
var progressEvent = new ProgressEvent('progress', {
|
||||
loaded: evt.progress.bytesSent,
|
||||
total: evt.progress.totalBytesToSend,
|
||||
target: evt.resultFile
|
||||
});
|
||||
progressEvent.lengthComputable = true;
|
||||
successCallback(progressEvent, { keepCallback: true });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var fileTransferOps = [];
|
||||
|
||||
function FileTransferOperation(state, promise) {
|
||||
@ -73,7 +163,7 @@ module.exports = {
|
||||
exec(win, fail, 'FileTransfer', 'upload',
|
||||
[filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
|
||||
*/
|
||||
upload:function(successCallback, errorCallback, options) {
|
||||
upload: function (successCallback, errorCallback, options) {
|
||||
var filePath = options[0];
|
||||
var server = options[1];
|
||||
var fileKey = options[2] || 'source';
|
||||
@ -89,7 +179,129 @@ exec(win, fail, 'FileTransfer', 'upload',
|
||||
var isMultipart = typeof headers["Content-Type"] === 'undefined';
|
||||
|
||||
if (!filePath || (typeof filePath !== 'string')) {
|
||||
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR,null,server));
|
||||
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, null, server));
|
||||
return;
|
||||
}
|
||||
|
||||
if (filePath.indexOf("data:") === 0 && filePath.indexOf("base64") !== -1) {
|
||||
// First a DataWriter object is created, backed by an in-memory stream where
|
||||
// the data will be stored.
|
||||
var writer = Windows.Storage.Streams.DataWriter(new Windows.Storage.Streams.InMemoryRandomAccessStream());
|
||||
writer.unicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.utf8;
|
||||
writer.byteOrder = Windows.Storage.Streams.ByteOrder.littleEndian;
|
||||
|
||||
var commaIndex = filePath.indexOf(",");
|
||||
if (commaIndex === -1) {
|
||||
errorCallback(new FTErr(FTErr.INVALID_URL_ERR, fileName, server, null, null, "No comma in data: URI"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create internal download operation object
|
||||
fileTransferOps[uploadId] = new FileTransferOperation(FileTransferOperation.PENDING, null);
|
||||
|
||||
var fileDataString = filePath.substr(commaIndex + 1);
|
||||
|
||||
function stringToByteArray(str) {
|
||||
var byteCharacters = atob(str);
|
||||
var byteNumbers = new Array(byteCharacters.length);
|
||||
for (var i = 0; i < byteCharacters.length; i++) {
|
||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
}
|
||||
return new Uint8Array(byteNumbers);
|
||||
};
|
||||
|
||||
// setting request headers for uploader
|
||||
var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
|
||||
uploader.method = httpMethod;
|
||||
for (var header in headers) {
|
||||
if (headers.hasOwnProperty(header)) {
|
||||
uploader.setRequestHeader(header, headers[header]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isMultipart) {
|
||||
// adding params supplied to request payload
|
||||
var multipartParams = '';
|
||||
for (var key in params) {
|
||||
if (params.hasOwnProperty(key)) {
|
||||
multipartParams += LINE_START + BOUNDARY + LINE_END;
|
||||
multipartParams += "Content-Disposition: form-data; name=\"" + key + "\"";
|
||||
multipartParams += LINE_END + LINE_END;
|
||||
multipartParams += params[key];
|
||||
multipartParams += LINE_END;
|
||||
}
|
||||
}
|
||||
|
||||
var multipartFile = LINE_START + BOUNDARY + LINE_END;
|
||||
multipartFile += "Content-Disposition: form-data; name=\"file\";";
|
||||
multipartFile += " filename=\"" + fileName + "\"" + LINE_END;
|
||||
multipartFile += "Content-Type: " + mimeType + LINE_END + LINE_END;
|
||||
|
||||
var bound = LINE_END + LINE_START + BOUNDARY + LINE_END;
|
||||
|
||||
uploader.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
|
||||
writer.writeString(multipartParams);
|
||||
writer.writeString(multipartFile);
|
||||
writer.writeBytes(stringToByteArray(fileDataString));
|
||||
writer.writeString(bound);
|
||||
} else {
|
||||
writer.writeBytes(stringToByteArray(fileDataString));
|
||||
}
|
||||
|
||||
var stream;
|
||||
|
||||
// The call to store async sends the actual contents of the writer
|
||||
// to the backing stream.
|
||||
writer.storeAsync().then(function () {
|
||||
// For the in-memory stream implementation we are using, the flushAsync call
|
||||
// is superfluous, but other types of streams may require it.
|
||||
return writer.flushAsync();
|
||||
}).then(function () {
|
||||
// We detach the stream to prolong its useful lifetime. Were we to fail
|
||||
// to detach the stream, the call to writer.close() would close the underlying
|
||||
// stream, preventing its subsequent use by the DataReader below. Most clients
|
||||
// of DataWriter will have no reason to use the underlying stream after
|
||||
// writer.close() is called, and will therefore have no reason to call
|
||||
// writer.detachStream(). Note that once we detach the stream, we assume
|
||||
// responsibility for closing the stream subsequently; after the stream
|
||||
// has been detached, a call to writer.close() will have no effect on the stream.
|
||||
stream = writer.detachStream();
|
||||
// Make sure the stream is read from the beginning in the reader
|
||||
// we are creating below.
|
||||
stream.seek(0);
|
||||
// Most DataWriter clients will not call writer.detachStream(),
|
||||
// and furthermore will be working with a file-backed or network-backed stream,
|
||||
// rather than an in-memory-stream. In such cases, it would be particularly
|
||||
// important to call writer.close(). Doing so is always a best practice.
|
||||
writer.close();
|
||||
|
||||
if (alreadyCancelled(uploadId)) {
|
||||
errorCallback(new FTErr(FTErr.ABORT_ERR, nativePathToCordova(filePath), server));
|
||||
return;
|
||||
}
|
||||
|
||||
// create download object. This will throw an exception if URL is malformed
|
||||
var uri = new Windows.Foundation.Uri(server);
|
||||
|
||||
var createUploadOperation;
|
||||
try {
|
||||
createUploadOperation = uploader.createUploadFromStreamAsync(uri, stream);
|
||||
} catch (e) {
|
||||
errorCallback(new FTErr(FTErr.INVALID_URL_ERR));
|
||||
return;
|
||||
}
|
||||
|
||||
createUploadOperation.then(
|
||||
function (upload) {
|
||||
doUpload(upload, uploadId, filePath, server, successCallback, errorCallback);
|
||||
},
|
||||
function (err) {
|
||||
var errorObj = new FTErr(FTErr.INVALID_URL_ERR);
|
||||
errorObj.exception = err;
|
||||
errorCallback(errorObj);
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -103,6 +315,7 @@ exec(win, fail, 'FileTransfer', 'upload',
|
||||
filePath = filePath.replace('cdvfile://localhost/persistent', appData.localFolder.path)
|
||||
.replace('cdvfile://localhost/temporary', appData.temporaryFolder.path);
|
||||
}
|
||||
|
||||
// normalize path separators
|
||||
filePath = cordovaPathToNative(filePath);
|
||||
|
||||
@ -112,10 +325,10 @@ exec(win, fail, 'FileTransfer', 'upload',
|
||||
Windows.Storage.StorageFile.getFileFromPathAsync(filePath)
|
||||
.then(function (storageFile) {
|
||||
|
||||
if(!fileName) {
|
||||
if (!fileName) {
|
||||
fileName = storageFile.name;
|
||||
}
|
||||
if(!mimeType) {
|
||||
if (!mimeType) {
|
||||
// use the actual content type of the file, probably this should be the default way.
|
||||
// other platforms probably can't look this up.
|
||||
mimeType = storageFile.contentType;
|
||||
@ -168,90 +381,7 @@ exec(win, fail, 'FileTransfer', 'upload',
|
||||
|
||||
createUploadOperation.then(
|
||||
function (upload) {
|
||||
if (alreadyCancelled(uploadId)) {
|
||||
errorCallback(new FTErr(FTErr.ABORT_ERR, nativePathToCordova(filePath), server));
|
||||
return;
|
||||
}
|
||||
|
||||
// update internal TransferOperation object with newly created promise
|
||||
var uploadOperation = upload.startAsync();
|
||||
fileTransferOps[uploadId].promise = uploadOperation;
|
||||
|
||||
uploadOperation.then(
|
||||
function (result) {
|
||||
// Update TransferOperation object with new state, delete promise property
|
||||
// since it is not actual anymore
|
||||
var currentUploadOp = fileTransferOps[uploadId];
|
||||
if (currentUploadOp) {
|
||||
currentUploadOp.state = FileTransferOperation.DONE;
|
||||
currentUploadOp.promise = null;
|
||||
}
|
||||
|
||||
var response = result.getResponseInformation();
|
||||
var ftResult = new FileUploadResult(result.progress.bytesSent, response.statusCode, '');
|
||||
|
||||
// if server's response doesn't contain any data, then resolve operation now
|
||||
if (result.progress.bytesReceived === 0) {
|
||||
successCallback(ftResult);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise create a data reader, attached to response stream to get server's response
|
||||
var reader = new Windows.Storage.Streams.DataReader(result.getResultStreamAt(0));
|
||||
reader.loadAsync(result.progress.bytesReceived).then(function (size) {
|
||||
ftResult.response = reader.readString(size);
|
||||
successCallback(ftResult);
|
||||
reader.close();
|
||||
});
|
||||
},
|
||||
function (error) {
|
||||
var source = nativePathToCordova(filePath);
|
||||
|
||||
// Handle download error here.
|
||||
// Wrap this routines into promise due to some async methods
|
||||
var getTransferError = new WinJS.Promise(function(resolve) {
|
||||
if (error.message === 'Canceled') {
|
||||
// If download was cancelled, message property will be specified
|
||||
resolve(new FTErr(FTErr.ABORT_ERR, source, server, null, null, error));
|
||||
} else {
|
||||
// in the other way, try to get response property
|
||||
var response = upload.getResponseInformation();
|
||||
if (!response) {
|
||||
resolve(new FTErr(FTErr.CONNECTION_ERR, source, server));
|
||||
} else {
|
||||
var reader = new Windows.Storage.Streams.DataReader(upload.getResultStreamAt(0));
|
||||
reader.loadAsync(upload.progress.bytesReceived).then(function (size) {
|
||||
var responseText = reader.readString(size);
|
||||
resolve(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, server, response.statusCode, responseText, error));
|
||||
reader.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Update TransferOperation object with new state, delete promise property
|
||||
// since it is not actual anymore
|
||||
var currentUploadOp = fileTransferOps[uploadId];
|
||||
if (currentUploadOp) {
|
||||
currentUploadOp.state = FileTransferOperation.CANCELLED;
|
||||
currentUploadOp.promise = null;
|
||||
}
|
||||
|
||||
// Report the upload error back
|
||||
getTransferError.then(function(transferError) {
|
||||
errorCallback(transferError);
|
||||
});
|
||||
},
|
||||
function (evt) {
|
||||
var progressEvent = new ProgressEvent('progress', {
|
||||
loaded: evt.progress.bytesSent,
|
||||
total: evt.progress.totalBytesToSend,
|
||||
target: evt.resultFile
|
||||
});
|
||||
progressEvent.lengthComputable = true;
|
||||
successCallback(progressEvent, { keepCallback: true });
|
||||
}
|
||||
);
|
||||
doUpload(upload, uploadId, filePath, server, successCallback, errorCallback);
|
||||
},
|
||||
function (err) {
|
||||
var errorObj = new FTErr(FTErr.INVALID_URL_ERR);
|
||||
@ -259,7 +389,7 @@ exec(win, fail, 'FileTransfer', 'upload',
|
||||
errorCallback(errorObj);
|
||||
}
|
||||
);
|
||||
}, function(err) {
|
||||
}, function (err) {
|
||||
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, fileName, server, null, null, err));
|
||||
});
|
||||
},
|
||||
@ -350,6 +480,8 @@ exec(win, fail, 'FileTransfer', 'upload',
|
||||
// Passing null as error callback here because downloaded file should exist in any case
|
||||
// otherwise the error callback will be hit during file creation in another place
|
||||
FileProxy.resolveLocalFileSystemURI(successCallback, null, [nativeURI]);
|
||||
}, function(error) {
|
||||
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, target, null, null, error));
|
||||
});
|
||||
}, function(error) {
|
||||
|
||||
@ -407,7 +539,7 @@ exec(win, fail, 'FileTransfer', 'upload',
|
||||
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, target, null, null, error));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var fileNotFoundErrorCallback = function(error) {
|
||||
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, target, null, null, error));
|
||||
};
|
||||
|
@ -39,6 +39,9 @@ exports.defineAutoTests = function () {
|
||||
var UPLOAD_TIMEOUT = 7 * ONE_SECOND;
|
||||
var ABORT_DELAY = 100; // for abort() tests
|
||||
var LATIN1_SYMBOLS = '¥§©ÆÖÑøøø¼';
|
||||
var DATA_URI_PREFIX = "data:image/png;base64,";
|
||||
var DATA_URI_CONTENT = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
|
||||
var DATA_URI_CONTENT_LENGTH = 85; // bytes. (This is the raw file size: used https://en.wikipedia.org/wiki/File:Red-dot-5px.png from https://en.wikipedia.org/wiki/Data_URI_scheme)
|
||||
|
||||
// config for upload test server
|
||||
// NOTE:
|
||||
@ -734,7 +737,7 @@ exports.defineAutoTests = function () {
|
||||
}
|
||||
});
|
||||
}, unexpectedCallbacks.httpFail);
|
||||
}, DOWNLOAD_TIMEOUT);
|
||||
}, DOWNLOAD_TIMEOUT * 2);
|
||||
|
||||
it("filetransfer.spec.36 should handle non-UTF8 encoded download response", function (done) {
|
||||
|
||||
@ -1148,6 +1151,92 @@ exports.defineAutoTests = function () {
|
||||
// NOTE: removing uploadOptions cause Android to timeout
|
||||
transfer.upload(localFilePath, fileURL, uploadWin, unexpectedCallbacks.httpFail, uploadOptions);
|
||||
}, UPLOAD_TIMEOUT);
|
||||
|
||||
it("filetransfer.spec.38 should be able to upload a file using data: source uri", function (done) {
|
||||
|
||||
var fileURL = SERVER + "/upload";
|
||||
|
||||
var uploadWin = function (uploadResult) {
|
||||
|
||||
verifyUpload(uploadResult);
|
||||
|
||||
var obj = null;
|
||||
try {
|
||||
obj = JSON.parse(uploadResult.response);
|
||||
expect(obj.files.file.size).toBe(DATA_URI_CONTENT_LENGTH);
|
||||
} catch (e) {
|
||||
expect(obj).not.toBeNull("returned data from server should be valid json");
|
||||
}
|
||||
|
||||
if (cordova.platformId === "ios") {
|
||||
expect(uploadResult.headers).toBeDefined("Expected headers to be defined.");
|
||||
expect(uploadResult.headers["Content-Type"]).toBeDefined("Expected content-type header to be defined.");
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
var dataUri = DATA_URI_PREFIX + DATA_URI_CONTENT;
|
||||
// NOTE: removing uploadOptions cause Android to timeout
|
||||
transfer.upload(dataUri, fileURL, uploadWin, function (err) {
|
||||
console.error('err: ' + JSON.stringify(err));
|
||||
expect(err).not.toBeDefined();
|
||||
done();
|
||||
}, uploadOptions);
|
||||
}, UPLOAD_TIMEOUT);
|
||||
|
||||
it("filetransfer.spec.39 should be able to upload a file using data: source uri (non-multipart)", function (done) {
|
||||
|
||||
var fileURL = SERVER + "/upload";
|
||||
|
||||
var uploadWin = function (uploadResult) {
|
||||
|
||||
expect(uploadResult.responseCode).toBe(200);
|
||||
expect(uploadResult.bytesSent).toBeGreaterThan(0);
|
||||
|
||||
if (cordova.platformId === "ios") {
|
||||
expect(uploadResult.headers).toBeDefined("Expected headers to be defined.");
|
||||
expect(uploadResult.headers["Content-Type"]).toBeDefined("Expected content-type header to be defined.");
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
// Content-Type header disables multipart
|
||||
uploadOptions.headers = {
|
||||
"Content-Type": "image/png"
|
||||
};
|
||||
|
||||
var dataUri = DATA_URI_PREFIX + DATA_URI_CONTENT;
|
||||
// NOTE: removing uploadOptions cause Android to timeout
|
||||
transfer.upload(dataUri, fileURL, uploadWin, unexpectedCallbacks.httpFail, uploadOptions);
|
||||
}, UPLOAD_TIMEOUT);
|
||||
|
||||
it("filetransfer.spec.40 should not fail to upload a file using data: source uri when the data is empty", function (done) {
|
||||
|
||||
var fileURL = SERVER + "/upload";
|
||||
|
||||
var dataUri = DATA_URI_PREFIX;
|
||||
// NOTE: removing uploadOptions cause Android to timeout
|
||||
transfer.upload(dataUri, fileURL, done, unexpectedCallbacks.httpFail, uploadOptions);
|
||||
}, UPLOAD_TIMEOUT);
|
||||
|
||||
it("filetransfer.spec.41 should not fail to upload a file using data: source uri when the data is empty (non-multipart)", function (done) {
|
||||
|
||||
var fileURL = SERVER + "/upload";
|
||||
|
||||
// Content-Type header disables multipart
|
||||
uploadOptions.headers = {
|
||||
"Content-Type": "image/png"
|
||||
};
|
||||
|
||||
// turn off the onprogress handler
|
||||
transfer.onprogress = function () { };
|
||||
|
||||
var dataUri = DATA_URI_PREFIX;
|
||||
// NOTE: removing uploadOptions cause Android to timeout
|
||||
transfer.upload(dataUri, fileURL, done, unexpectedCallbacks.httpFail, uploadOptions);
|
||||
}, UPLOAD_TIMEOUT);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user