Cordova 文件上传无法在 windows phone 上运行
Cordova-file-upload not working on windows phone
简短版本:
这一小段代码永远不会有回调。我在msdn之类的地方环顾四周,但找不到解决方案。在我看来,BackgroundTransfer 的 BackgroundUploader 的 createUploadAsync 的 startAsync 开始了,但随后什么也没做。它没有错误或成功回调。
并且 "rarely" 它在再次停止工作之前实际上工作了几次。对设备进行硬重置似乎也无法解决此问题。网络连接是通过本地局域网进行的。与服务器的连接稳定。我是 运行 API 在 visual studio 的本地机器上的副本,其中请求成功工作。
我试图回归到 cordova 5.1.1 和 cordova-plugin-file-transfer 1.3.0 和 1.2.0,看看它是否与我使用的版本有任何关系。
我正在连接的服务器适用于任何其他设备。值得注意的是,这整个功能似乎在 windows 模拟器中工作,这让我认为这可能是一个特定的设备问题?
为了 windows phone 8.1
,我可能割伤了自己
var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
uploader.createUploadAsync(uri, transferParts).then(function(result) {
var uploadOperation = upload.startAsync();
fileTransferOps[uploadId].promise = uploadOperation;
uploadOperation.then(successFunc, errorFunc);
}, errorCallBack);
编辑:
我为此操作设置了超时,以便它在 25 秒后中止,它确实如此。在所有其他 (iOS/Android 4.2/5.x) 设备上,这是即时的。并不是 Windows Phone 由于某种原因变慢了,因为请求在那里的时间超过 60 分钟。也许 BackgroundUploader() 默默地失败了……会调查这个。
Edit2:在此处提交错误报告:https://issues.apache.org/jira/browse/CB-10254
我试图帮助解决这个问题的其他方法是禁用时间和日期的同步,重新启动设备,它就像一个魅力...... 片刻。进一步的调试表明我所有的请求都被取消或挂起。
下面是那些有兴趣帮助我深入研究的无聊内容。
代码示例:
$scope.album = {
uploadPhotos: function (photos) {
var promises = [];
for (var i = 0; i < photos.length; i++) {
// Windows phone doesn't work so we have to add a dirty workaround, as usual.
if (ionic.Platform.isWindowsPhone()) {
photos[i] = "cdvfile://localhost/persistent/" + decodeURIComponent(photos[i].split("/").pop());
}
var scannInvoice = parseToBool($localstorage.get("remindInvoiceScan")) ? 1 : 0;
promises.push($cordovaFileTransfer.upload("***HTTP Development/HTTPS Production***", photos[i], {
fileKey: "file",
fileName: photos[i].split("/").pop(),
httpMethod: "POST",
timeout: 25000,
chunkedMode: false,
contentType: "application/json; charset=utf-8",
// mimeType: "image/png",
params: { 'scannInvoice': scannInvoice },
headers: { 'Authorization': 'Token ' + $settings.accesstoken }
}).then(function (result) {
$fileService.setFotoUploaded(result.response);
}, function (err) {
$logService.handleException("PhotoCtrl", "Afbeelding is niet geupload", "Er is een onbekende fout opgetreden.", err, true, false, true, true);
}));
} // Some $q.all call comes here that handles everything.
}
}
在FileTransfer.js
FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, trustAllHosts) {
argscheck.checkArgs('ssFFO*', 'FileTransfer.upload', arguments);
// check for options
var fileKey = null;
var fileName = null;
var mimeType = null;
var params = null;
var chunkedMode = true;
var headers = null;
var httpMethod = null;
var basicAuthHeader = getBasicAuthHeader(server);
if (basicAuthHeader) {
server = server.replace(getUrlCredentials(server) + '@', '');
options = options || {};
options.headers = options.headers || {};
options.headers[basicAuthHeader.name] = basicAuthHeader.value;
}
if (options) {
fileKey = options.fileKey;
fileName = options.fileName;
mimeType = options.mimeType;
headers = options.headers;
httpMethod = options.httpMethod || "POST";
if (httpMethod.toUpperCase() == "PUT"){
httpMethod = "PUT";
} else {
httpMethod = "POST";
}
if (options.chunkedMode !== null || typeof options.chunkedMode != "undefined") {
chunkedMode = options.chunkedMode;
}
if (options.params) {
params = options.params;
}
else {
params = {};
}
}
if (cordova.platformId === "windowsphone") {
headers = headers && convertHeadersToArray(headers);
params = params && convertHeadersToArray(params);
}
var fail = errorCallback && function(e) {
var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception);
errorCallback(error);
};
var self = this;
var win = function(result) {
if (typeof result.lengthComputable != "undefined") {
if (self.onprogress) {
self.onprogress(newProgressEvent(result));
}
} else {
successCallback && successCallback(result);
}
};
exec(win, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
};
并在 FileTransferProxy.js
module.exports = {
/*
exec(win, fail, 'FileTransfer', 'upload',
[filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
*/
upload:function(successCallback, errorCallback, options) {
var filePath = options[0];
var server = options[1];
var fileKey = options[2] || 'source';
var fileName = options[3];
var mimeType = options[4];
var params = options[5];
// var trustAllHosts = options[6]; // todo
// var chunkedMode = options[7]; // todo
var headers = options[8] || {};
var uploadId = options[9];
if (!filePath || (typeof filePath !== 'string')) {
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR,null,server));
return;
}
if (filePath.substr(0, 8) === "file:///") {
filePath = appData.localFolder.path + filePath.substr(8).split("/").join("\");
} else if (filePath.indexOf('ms-appdata:///') === 0) {
// Handle 'ms-appdata' scheme
filePath = filePath.replace('ms-appdata:///local', appData.localFolder.path)
.replace('ms-appdata:///temp', appData.temporaryFolder.path);
}
// normalize path separators
filePath = cordovaPathToNative(filePath);
// Create internal download operation object
fileTransferOps[uploadId] = new FileTransferOperation(FileTransferOperation.PENDING, null);
Windows.Storage.StorageFile.getFileFromPathAsync(filePath)
.then(function (storageFile) {
if(!fileName) {
fileName = storageFile.name;
}
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;
}
// check if download isn't already cancelled
var uploadOp = fileTransferOps[uploadId];
if (uploadOp && uploadOp.state === FileTransferOperation.CANCELLED) {
// Here we should call errorCB with ABORT_ERR error
errorCallback(new FTErr(FTErr.ABORT_ERR, nativePathToCordova(filePath), server));
return;
}
// setting request headers for uploader
var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
for (var header in headers) {
if (headers.hasOwnProperty(header)) {
uploader.setRequestHeader(header, headers[header]);
}
}
// adding params supplied to request payload
var transferParts = [];
for (var key in params) {
if (params.hasOwnProperty(key)) {
var contentPart = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart();
contentPart.setHeader("Content-Disposition", "form-data; name=\"" + key + "\"");
contentPart.setText(params[key]);
transferParts.push(contentPart);
}
}
// Adding file to upload to request payload
var fileToUploadPart = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart(fileKey, fileName);
fileToUploadPart.setFile(storageFile);
transferParts.push(fileToUploadPart);
// create download object. This will throw an exception if URL is malformed
var uri = new Windows.Foundation.Uri(server);
try {
uploader.createUploadAsync(uri, transferParts).then(
function (upload) {
// 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;
}
// Cleanup, remove incompleted file
getTransferError.then(function(transferError) {
storageFile.deleteAsync().then(function() {
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 });
}
);
},
function (err) {
var errorObj = new FTErr(FTErr.INVALID_URL_ERR);
errorObj.exception = err;
errorCallback(errorObj);
}
);
} catch (e) {
errorCallback(new FTErr(FTErr.INVALID_URL_ERR));
}
}, function(err) {
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, server, server, null, null, err));
});
},
};
我的设置信息:
Windows Phone 8.1, Nokia Lumia 520
在我的taco.json
{
"cordova-cli": "5.4.1"
}
使用windows平台4.2.0
当前添加的插件
<vs:plugin name="cordova-plugin-device" version="1.1.0" />
<vs:plugin name="cordova-plugin-whitelist" version="1.2.0" />
<vs:plugin name="cordova-plugin-file" version="3.0.0" />
<vs:plugin name="cordova-plugin-network-information" version="1.1.0" />
<vs:plugin name="cordova-plugin-inappbrowser" version="1.1.1" />
<vs:plugin name="cordova-plugin-statusbar" version="2.0.0" />
<vs:plugin name="cordova-plugin-camera" version="2.0.0" src="https://github.com/apache/cordova-plugin-camera" />
<vs:plugin name="cordova-plugin-file-transfer" version="1.4.0" />
最后在我的 index.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' cdvfile://*; data: gap: https://ssl.gstatic.com; style-src 'unsafe-inline' 'self' cdvfile://*; script-src 'self' 'unsafe-eval' cdvfile://*">
<meta name="format-detection" content="telephone=no">
<title></title>
<!-- stylesheets -->
<link href="css/ionic.min.css" rel="stylesheet" />
<link href="css/ionic-overrides.css" rel="stylesheet" />
<link href="css/angular-chart.css" rel="stylesheet" />
<link href="css/isteven-omni-bar.css" rel="stylesheet" />
<!-- library -->
<script src="cordova.js"></script>
<script src="scripts/platformOverrides.js"></script>
<script src="scripts/ionic.bundle.custom.js"></script>
<script src="scripts/ng-cordova.js"></script>
<!-- application -->
<script src="js/app.js"></script>
<script src="js/services/localstorage.js"></script>
<script src="js/services/settings.js"></script>
<!-- config -->
<script src="js/config/ionicPlatform.js"></script>
<script src="js/config/compileProvider.js"></script>
<script src="js/config/stateProvider.js"></script>
<script src="js/config/formatFilters.js"></script>
<script src="js/config/directives.js"></script>
<!-- controllers -->
<script src="js/controllers/LoginController.js"></script>
<script src="js/controllers/AppController.js"></script>
<script src="js/controllers/DashboardController.js"></script>
<script src="js/controllers/PhotoController.js"></script>
<script src="js/controllers/AdministrationController.js"></script>
<script src="js/controllers/MutationController.js"></script>
<!-- services -->
<script src="js/services/administrationService.js"></script>
<script src="js/services/fileService.js"></script>
<script src="js/services/logService.js"></script>
<!-- scripts -->
<script src="scripts/helpers.js"></script>
<script src="scripts/chart/highcharts.js"></script>
<script src="scripts/chart/highcharts-ng.js"></script>
<script src="scripts/isteven-omni-bar.js"></script>
</head>
出现这个问题后,我通过以下步骤始终如一地解决了这个问题。
- 卸载开发应用。
- 在您的项目中删除文件传输插件。
- 添加文件传输插件的 1.4.1-dev 版本(包括对
请求头)。
- 从项目文件夹中删除 bld、build、platforms、plugins 文件夹(它们将使用 visual studio 的 apache cordova 工具重建)
- 硬重置 windows phone。
- 重建。
简短版本:
这一小段代码永远不会有回调。我在msdn之类的地方环顾四周,但找不到解决方案。在我看来,BackgroundTransfer 的 BackgroundUploader 的 createUploadAsync 的 startAsync 开始了,但随后什么也没做。它没有错误或成功回调。
并且 "rarely" 它在再次停止工作之前实际上工作了几次。对设备进行硬重置似乎也无法解决此问题。网络连接是通过本地局域网进行的。与服务器的连接稳定。我是 运行 API 在 visual studio 的本地机器上的副本,其中请求成功工作。
我试图回归到 cordova 5.1.1 和 cordova-plugin-file-transfer 1.3.0 和 1.2.0,看看它是否与我使用的版本有任何关系。
我正在连接的服务器适用于任何其他设备。值得注意的是,这整个功能似乎在 windows 模拟器中工作,这让我认为这可能是一个特定的设备问题?
为了 windows phone 8.1
,我可能割伤了自己var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
uploader.createUploadAsync(uri, transferParts).then(function(result) {
var uploadOperation = upload.startAsync();
fileTransferOps[uploadId].promise = uploadOperation;
uploadOperation.then(successFunc, errorFunc);
}, errorCallBack);
编辑: 我为此操作设置了超时,以便它在 25 秒后中止,它确实如此。在所有其他 (iOS/Android 4.2/5.x) 设备上,这是即时的。并不是 Windows Phone 由于某种原因变慢了,因为请求在那里的时间超过 60 分钟。也许 BackgroundUploader() 默默地失败了……会调查这个。
Edit2:在此处提交错误报告:https://issues.apache.org/jira/browse/CB-10254 我试图帮助解决这个问题的其他方法是禁用时间和日期的同步,重新启动设备,它就像一个魅力...... 片刻。进一步的调试表明我所有的请求都被取消或挂起。
下面是那些有兴趣帮助我深入研究的无聊内容。
代码示例:
$scope.album = {
uploadPhotos: function (photos) {
var promises = [];
for (var i = 0; i < photos.length; i++) {
// Windows phone doesn't work so we have to add a dirty workaround, as usual.
if (ionic.Platform.isWindowsPhone()) {
photos[i] = "cdvfile://localhost/persistent/" + decodeURIComponent(photos[i].split("/").pop());
}
var scannInvoice = parseToBool($localstorage.get("remindInvoiceScan")) ? 1 : 0;
promises.push($cordovaFileTransfer.upload("***HTTP Development/HTTPS Production***", photos[i], {
fileKey: "file",
fileName: photos[i].split("/").pop(),
httpMethod: "POST",
timeout: 25000,
chunkedMode: false,
contentType: "application/json; charset=utf-8",
// mimeType: "image/png",
params: { 'scannInvoice': scannInvoice },
headers: { 'Authorization': 'Token ' + $settings.accesstoken }
}).then(function (result) {
$fileService.setFotoUploaded(result.response);
}, function (err) {
$logService.handleException("PhotoCtrl", "Afbeelding is niet geupload", "Er is een onbekende fout opgetreden.", err, true, false, true, true);
}));
} // Some $q.all call comes here that handles everything.
}
}
在FileTransfer.js
FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, trustAllHosts) {
argscheck.checkArgs('ssFFO*', 'FileTransfer.upload', arguments);
// check for options
var fileKey = null;
var fileName = null;
var mimeType = null;
var params = null;
var chunkedMode = true;
var headers = null;
var httpMethod = null;
var basicAuthHeader = getBasicAuthHeader(server);
if (basicAuthHeader) {
server = server.replace(getUrlCredentials(server) + '@', '');
options = options || {};
options.headers = options.headers || {};
options.headers[basicAuthHeader.name] = basicAuthHeader.value;
}
if (options) {
fileKey = options.fileKey;
fileName = options.fileName;
mimeType = options.mimeType;
headers = options.headers;
httpMethod = options.httpMethod || "POST";
if (httpMethod.toUpperCase() == "PUT"){
httpMethod = "PUT";
} else {
httpMethod = "POST";
}
if (options.chunkedMode !== null || typeof options.chunkedMode != "undefined") {
chunkedMode = options.chunkedMode;
}
if (options.params) {
params = options.params;
}
else {
params = {};
}
}
if (cordova.platformId === "windowsphone") {
headers = headers && convertHeadersToArray(headers);
params = params && convertHeadersToArray(params);
}
var fail = errorCallback && function(e) {
var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception);
errorCallback(error);
};
var self = this;
var win = function(result) {
if (typeof result.lengthComputable != "undefined") {
if (self.onprogress) {
self.onprogress(newProgressEvent(result));
}
} else {
successCallback && successCallback(result);
}
};
exec(win, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
};
并在 FileTransferProxy.js
module.exports = {
/*
exec(win, fail, 'FileTransfer', 'upload',
[filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
*/
upload:function(successCallback, errorCallback, options) {
var filePath = options[0];
var server = options[1];
var fileKey = options[2] || 'source';
var fileName = options[3];
var mimeType = options[4];
var params = options[5];
// var trustAllHosts = options[6]; // todo
// var chunkedMode = options[7]; // todo
var headers = options[8] || {};
var uploadId = options[9];
if (!filePath || (typeof filePath !== 'string')) {
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR,null,server));
return;
}
if (filePath.substr(0, 8) === "file:///") {
filePath = appData.localFolder.path + filePath.substr(8).split("/").join("\");
} else if (filePath.indexOf('ms-appdata:///') === 0) {
// Handle 'ms-appdata' scheme
filePath = filePath.replace('ms-appdata:///local', appData.localFolder.path)
.replace('ms-appdata:///temp', appData.temporaryFolder.path);
}
// normalize path separators
filePath = cordovaPathToNative(filePath);
// Create internal download operation object
fileTransferOps[uploadId] = new FileTransferOperation(FileTransferOperation.PENDING, null);
Windows.Storage.StorageFile.getFileFromPathAsync(filePath)
.then(function (storageFile) {
if(!fileName) {
fileName = storageFile.name;
}
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;
}
// check if download isn't already cancelled
var uploadOp = fileTransferOps[uploadId];
if (uploadOp && uploadOp.state === FileTransferOperation.CANCELLED) {
// Here we should call errorCB with ABORT_ERR error
errorCallback(new FTErr(FTErr.ABORT_ERR, nativePathToCordova(filePath), server));
return;
}
// setting request headers for uploader
var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
for (var header in headers) {
if (headers.hasOwnProperty(header)) {
uploader.setRequestHeader(header, headers[header]);
}
}
// adding params supplied to request payload
var transferParts = [];
for (var key in params) {
if (params.hasOwnProperty(key)) {
var contentPart = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart();
contentPart.setHeader("Content-Disposition", "form-data; name=\"" + key + "\"");
contentPart.setText(params[key]);
transferParts.push(contentPart);
}
}
// Adding file to upload to request payload
var fileToUploadPart = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart(fileKey, fileName);
fileToUploadPart.setFile(storageFile);
transferParts.push(fileToUploadPart);
// create download object. This will throw an exception if URL is malformed
var uri = new Windows.Foundation.Uri(server);
try {
uploader.createUploadAsync(uri, transferParts).then(
function (upload) {
// 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;
}
// Cleanup, remove incompleted file
getTransferError.then(function(transferError) {
storageFile.deleteAsync().then(function() {
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 });
}
);
},
function (err) {
var errorObj = new FTErr(FTErr.INVALID_URL_ERR);
errorObj.exception = err;
errorCallback(errorObj);
}
);
} catch (e) {
errorCallback(new FTErr(FTErr.INVALID_URL_ERR));
}
}, function(err) {
errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, server, server, null, null, err));
});
},
};
我的设置信息:
Windows Phone 8.1, Nokia Lumia 520
在我的taco.json
{
"cordova-cli": "5.4.1"
}
使用windows平台4.2.0
当前添加的插件
<vs:plugin name="cordova-plugin-device" version="1.1.0" />
<vs:plugin name="cordova-plugin-whitelist" version="1.2.0" />
<vs:plugin name="cordova-plugin-file" version="3.0.0" />
<vs:plugin name="cordova-plugin-network-information" version="1.1.0" />
<vs:plugin name="cordova-plugin-inappbrowser" version="1.1.1" />
<vs:plugin name="cordova-plugin-statusbar" version="2.0.0" />
<vs:plugin name="cordova-plugin-camera" version="2.0.0" src="https://github.com/apache/cordova-plugin-camera" />
<vs:plugin name="cordova-plugin-file-transfer" version="1.4.0" />
最后在我的 index.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' cdvfile://*; data: gap: https://ssl.gstatic.com; style-src 'unsafe-inline' 'self' cdvfile://*; script-src 'self' 'unsafe-eval' cdvfile://*">
<meta name="format-detection" content="telephone=no">
<title></title>
<!-- stylesheets -->
<link href="css/ionic.min.css" rel="stylesheet" />
<link href="css/ionic-overrides.css" rel="stylesheet" />
<link href="css/angular-chart.css" rel="stylesheet" />
<link href="css/isteven-omni-bar.css" rel="stylesheet" />
<!-- library -->
<script src="cordova.js"></script>
<script src="scripts/platformOverrides.js"></script>
<script src="scripts/ionic.bundle.custom.js"></script>
<script src="scripts/ng-cordova.js"></script>
<!-- application -->
<script src="js/app.js"></script>
<script src="js/services/localstorage.js"></script>
<script src="js/services/settings.js"></script>
<!-- config -->
<script src="js/config/ionicPlatform.js"></script>
<script src="js/config/compileProvider.js"></script>
<script src="js/config/stateProvider.js"></script>
<script src="js/config/formatFilters.js"></script>
<script src="js/config/directives.js"></script>
<!-- controllers -->
<script src="js/controllers/LoginController.js"></script>
<script src="js/controllers/AppController.js"></script>
<script src="js/controllers/DashboardController.js"></script>
<script src="js/controllers/PhotoController.js"></script>
<script src="js/controllers/AdministrationController.js"></script>
<script src="js/controllers/MutationController.js"></script>
<!-- services -->
<script src="js/services/administrationService.js"></script>
<script src="js/services/fileService.js"></script>
<script src="js/services/logService.js"></script>
<!-- scripts -->
<script src="scripts/helpers.js"></script>
<script src="scripts/chart/highcharts.js"></script>
<script src="scripts/chart/highcharts-ng.js"></script>
<script src="scripts/isteven-omni-bar.js"></script>
</head>
出现这个问题后,我通过以下步骤始终如一地解决了这个问题。
- 卸载开发应用。
- 在您的项目中删除文件传输插件。
- 添加文件传输插件的 1.4.1-dev 版本(包括对 请求头)。
- 从项目文件夹中删除 bld、build、platforms、plugins 文件夹(它们将使用 visual studio 的 apache cordova 工具重建)
- 硬重置 windows phone。
- 重建。