Cordova/phonegap: FileTransferError.FILE_NOT_FOUND_ERR 带文件传输插件
Cordova/phonegap: FileTransferError.FILE_NOT_FOUND_ERR with file transfer plugin
在我的 phonegap 应用程序中,我用我的相机拍了一张照片,它按预期工作。
然后,我想将它发送到我的服务器。我发现发送 base64 编码的字符串是一种不好的做法,我认为最好的解决方案是使用文件传输插件。
所以,我添加了插件并写了这个:
function onPhotoURISuccess(imageURI) {
try{
var url = "myserver/addPhoto";
alert(url);
var options = new FileUploadOptions();
options.chunkedMode = false;
options.fileKey = "recFile";
var imagefilename = imageURI;
options.fileName = imagefilename;
options.mimeType = "image/jpeg";
options.params = { "token": APP.TOKEN};
var ft = new FileTransfer();
alert(imagefilename);
ft.upload(imageURI, url, win, fail, options);
}
catch (err) {
alert(err.message);
}
}
在 try 分支的最后一行,我得到错误 FileTransferError.FILE_NOT_FOUND_ERR.
在此行之前的警报中,我在警报中显示了路径(imagefilename 变量)。如果我尝试在我的 Android 设备中手动进入该路径,我找不到它。路径为file:///storage/emulated/0/Android/data/com.My.App/cache/1505307795417.jpg
所以,我尝试设置选项
saveToPhotoAlbum: true
检查图像是否已保存,我是否正确地在我的相册中看到了照片。不知道为什么发送的时候出错,会不会是路径不对?
我不认为问题出在服务器端,因为我什至在服务器日志中都看不到请求。
更新:
根据Anuj T的建议我也试过了,结果还是一样:
function onPhotoURISuccess(imageURI) {
var filepath;
window.resolveLocalFileSystemURL(imageURI, function success(fileEntry) {
// Do something with the FileEntry object, like write to it, upload it, etc.
// writeFile(fileEntry, imageURI);
filepath = fileEntry.fullPath;
alert("got file: " + fileEntry.fullPath);
// displayFileData(fileEntry.nativeURL, "Native URL");
try {
var url = "myUrl";
alert(url);
var options = new FileUploadOptions();
options.chunkedMode = false;
options.fileKey = "recFile";
var imagefilename = filepath;
options.fileName = imagefilename;
options.mimeType = "image/jpeg";
options.params = { "token": APP.TOKEN }; // if we need to send parameters to the server request
var ft = new FileTransfer();
alert(imagefilename);
alert(imageURI);
ft.upload(filepath, url, win, fail, options);
}
catch (err) {
alert(err.message);
}
}, function () {
// If don't get the FileEntry (which may happen when testing
// on some emulators), copy to a new FileEntry.
alert("file system fail");
createNewFileEntry(imgUri);
});
}
更新 2:
这是我的服务器端代码。
internal GenericResponse AddChiusuraPhoto(string token)
{
Utility.Logger("AddChiusuraPhoto");
var gr = new GenericResponse();
if (CheckToken(token, out IS_UTENZE utente))
{
try
{
var md5 = new md5Manager();
HttpPostedFile file = HttpContext.Current.Request.Files["recFile"];
if (file == null)
return null;
string targetFilePath = @"C:\ProgramData\" + file.FileName;
file.SaveAs(targetFilePath);
Utility.Logger("[AddChiusuraPhoto] Returning lista ");
return gr;
}
catch (Exception ex)
{
gr.ESITO = "[KO]";
gr.MESSAGGIO = ex.ToSafeString();
Utility.Logger("AddChiusuraPhoto " + gr.MESSAGGIO);
}
}
else
{
gr.ESITO = "[KO]";
gr.MESSAGGIO = "Utente non loggato, impossibile effettuare il logout.";
Utility.Logger("AddChiusuraPhoto " + gr.MESSAGGIO);
}
return gr;
}
请注意,这是一个 WCF。这是寻址部分:
[OperationContract]
[WebInvoke(UriTemplate = "chiusure/addPhoto", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
GenericResponse AddChiusuraPhoto(string token);
需要拍照获取FileEntry对象
如果您需要使用 FileEntry 对象,请在您的 CameraOptions 对象中将 destinationType 设置为 Camera.DestinationType.FILE_URI
更新代码
function getPicture(){
var srcType = Camera.PictureSourceType.CAMERA;
var options = setOptions(srcType);
//var func = createNewFileEntry;
navigator.camera.getPicture(function cameraSuccess(imageUri) {
//displayImage(imageUri);
// You may choose to copy the picture, save it somewhere, or upload.
//func(imageUri);
var filename = imageUri.substr(imageUri.lastIndexOf('/') + 1);
window.resolveLocalFileSystemURL(cordova.file.cacheDirectory, function success(dirEntry) {
// Do something with the FileEntry object, like write to it, upload it, etc.
// writeFile(fileEntry, imgUri);
console.log("got file: " + dirEntry.fullPath);
console.log("file name " + filename);
// JPEG file
dirEntry.getFile(filename, { create: true, exclusive: false }, function (fileEntry) {
// Do something with it, like write to it, upload it, etc.
// writeFile(fileEntry, imgUri);
console.log("got file: " + fileEntry.fullPath);
// displayFileData(fileEntry.fullPath, "File copied to");
upload(fileEntry);
}, onErrorCreateFile);
// displayFileData(fileEntry.nativeURL, "Native URL");
}, function () {
// If don't get the FileEntry (which may happen when testing
// on some emulators), copy to a new FileEntry.
//createNewFileEntry(imgUri);
});
//console.log(imageUri);
}, function cameraError(error) {
console.debug("Unable to obtain picture: " + error, "app");
}, options);
};
设置选项功能。
function setOptions(srcType) {
var options = {
// Some common settings are 20, 50, and 100
quality: 50,
destinationType: Camera.DestinationType.NATIVE_URI ,
// In this app, dynamically set the picture source, Camera or photo gallery
sourceType: srcType,
encodingType: Camera.EncodingType.JPEG,
mediaType: Camera.MediaType.PICTURE,
allowEdit: false,
saveToPhotoAlbum:false,
correctOrientation: true //Corrects Android orientation quirks
};
return options;
}
查看详细说明here。
上传文件到服务器
function upload(fileEntry) {
var fileURL = fileEntry.toURL();
var success = function (r) {
console.log("Successful upload..." + JSON.stringify(r));
console.log("Code = " + JSON.stringify(r.responseCode));
alert(JSON.stringify(r.response));
// displayFileData(fileEntry.fullPath + " (content uploaded to server)");
};
var fail = function (error) {
alert("An error has occurred: Code = " + error.code);
console.log("Error= " + error);
};
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1);
options.mimeType = "text/plain";
var params = {};
params.value1 = "test";
params.value2 = "param";
options.params = params;
var SERVER = "http://posttestserver.com/post.php";
var ft = new FileTransfer();
// SERVER must be a URL that can handle the request, like
// http://some.server.com/upload.php
ft.upload(fileURL, encodeURI(SERVER), success, fail, options);
}
当您收到成功警报时,您还可以检查您的参数是否上传到服务器,您将收到 link 成功。
希望对您有所帮助。
在我的 phonegap 应用程序中,我用我的相机拍了一张照片,它按预期工作。
然后,我想将它发送到我的服务器。我发现发送 base64 编码的字符串是一种不好的做法,我认为最好的解决方案是使用文件传输插件。
所以,我添加了插件并写了这个:
function onPhotoURISuccess(imageURI) {
try{
var url = "myserver/addPhoto";
alert(url);
var options = new FileUploadOptions();
options.chunkedMode = false;
options.fileKey = "recFile";
var imagefilename = imageURI;
options.fileName = imagefilename;
options.mimeType = "image/jpeg";
options.params = { "token": APP.TOKEN};
var ft = new FileTransfer();
alert(imagefilename);
ft.upload(imageURI, url, win, fail, options);
}
catch (err) {
alert(err.message);
}
}
在 try 分支的最后一行,我得到错误 FileTransferError.FILE_NOT_FOUND_ERR.
在此行之前的警报中,我在警报中显示了路径(imagefilename 变量)。如果我尝试在我的 Android 设备中手动进入该路径,我找不到它。路径为file:///storage/emulated/0/Android/data/com.My.App/cache/1505307795417.jpg
所以,我尝试设置选项
saveToPhotoAlbum: true
检查图像是否已保存,我是否正确地在我的相册中看到了照片。不知道为什么发送的时候出错,会不会是路径不对?
我不认为问题出在服务器端,因为我什至在服务器日志中都看不到请求。
更新:
根据Anuj T的建议我也试过了,结果还是一样:
function onPhotoURISuccess(imageURI) {
var filepath;
window.resolveLocalFileSystemURL(imageURI, function success(fileEntry) {
// Do something with the FileEntry object, like write to it, upload it, etc.
// writeFile(fileEntry, imageURI);
filepath = fileEntry.fullPath;
alert("got file: " + fileEntry.fullPath);
// displayFileData(fileEntry.nativeURL, "Native URL");
try {
var url = "myUrl";
alert(url);
var options = new FileUploadOptions();
options.chunkedMode = false;
options.fileKey = "recFile";
var imagefilename = filepath;
options.fileName = imagefilename;
options.mimeType = "image/jpeg";
options.params = { "token": APP.TOKEN }; // if we need to send parameters to the server request
var ft = new FileTransfer();
alert(imagefilename);
alert(imageURI);
ft.upload(filepath, url, win, fail, options);
}
catch (err) {
alert(err.message);
}
}, function () {
// If don't get the FileEntry (which may happen when testing
// on some emulators), copy to a new FileEntry.
alert("file system fail");
createNewFileEntry(imgUri);
});
}
更新 2:
这是我的服务器端代码。
internal GenericResponse AddChiusuraPhoto(string token)
{
Utility.Logger("AddChiusuraPhoto");
var gr = new GenericResponse();
if (CheckToken(token, out IS_UTENZE utente))
{
try
{
var md5 = new md5Manager();
HttpPostedFile file = HttpContext.Current.Request.Files["recFile"];
if (file == null)
return null;
string targetFilePath = @"C:\ProgramData\" + file.FileName;
file.SaveAs(targetFilePath);
Utility.Logger("[AddChiusuraPhoto] Returning lista ");
return gr;
}
catch (Exception ex)
{
gr.ESITO = "[KO]";
gr.MESSAGGIO = ex.ToSafeString();
Utility.Logger("AddChiusuraPhoto " + gr.MESSAGGIO);
}
}
else
{
gr.ESITO = "[KO]";
gr.MESSAGGIO = "Utente non loggato, impossibile effettuare il logout.";
Utility.Logger("AddChiusuraPhoto " + gr.MESSAGGIO);
}
return gr;
}
请注意,这是一个 WCF。这是寻址部分:
[OperationContract]
[WebInvoke(UriTemplate = "chiusure/addPhoto", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
GenericResponse AddChiusuraPhoto(string token);
需要拍照获取FileEntry对象
如果您需要使用 FileEntry 对象,请在您的 CameraOptions 对象中将 destinationType 设置为 Camera.DestinationType.FILE_URI
更新代码
function getPicture(){
var srcType = Camera.PictureSourceType.CAMERA;
var options = setOptions(srcType);
//var func = createNewFileEntry;
navigator.camera.getPicture(function cameraSuccess(imageUri) {
//displayImage(imageUri);
// You may choose to copy the picture, save it somewhere, or upload.
//func(imageUri);
var filename = imageUri.substr(imageUri.lastIndexOf('/') + 1);
window.resolveLocalFileSystemURL(cordova.file.cacheDirectory, function success(dirEntry) {
// Do something with the FileEntry object, like write to it, upload it, etc.
// writeFile(fileEntry, imgUri);
console.log("got file: " + dirEntry.fullPath);
console.log("file name " + filename);
// JPEG file
dirEntry.getFile(filename, { create: true, exclusive: false }, function (fileEntry) {
// Do something with it, like write to it, upload it, etc.
// writeFile(fileEntry, imgUri);
console.log("got file: " + fileEntry.fullPath);
// displayFileData(fileEntry.fullPath, "File copied to");
upload(fileEntry);
}, onErrorCreateFile);
// displayFileData(fileEntry.nativeURL, "Native URL");
}, function () {
// If don't get the FileEntry (which may happen when testing
// on some emulators), copy to a new FileEntry.
//createNewFileEntry(imgUri);
});
//console.log(imageUri);
}, function cameraError(error) {
console.debug("Unable to obtain picture: " + error, "app");
}, options);
};
设置选项功能。
function setOptions(srcType) {
var options = {
// Some common settings are 20, 50, and 100
quality: 50,
destinationType: Camera.DestinationType.NATIVE_URI ,
// In this app, dynamically set the picture source, Camera or photo gallery
sourceType: srcType,
encodingType: Camera.EncodingType.JPEG,
mediaType: Camera.MediaType.PICTURE,
allowEdit: false,
saveToPhotoAlbum:false,
correctOrientation: true //Corrects Android orientation quirks
};
return options;
}
查看详细说明here。
上传文件到服务器
function upload(fileEntry) {
var fileURL = fileEntry.toURL();
var success = function (r) {
console.log("Successful upload..." + JSON.stringify(r));
console.log("Code = " + JSON.stringify(r.responseCode));
alert(JSON.stringify(r.response));
// displayFileData(fileEntry.fullPath + " (content uploaded to server)");
};
var fail = function (error) {
alert("An error has occurred: Code = " + error.code);
console.log("Error= " + error);
};
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1);
options.mimeType = "text/plain";
var params = {};
params.value1 = "test";
params.value2 = "param";
options.params = params;
var SERVER = "http://posttestserver.com/post.php";
var ft = new FileTransfer();
// SERVER must be a URL that can handle the request, like
// http://some.server.com/upload.php
ft.upload(fileURL, encodeURI(SERVER), success, fail, options);
}
当您收到成功警报时,您还可以检查您的参数是否上传到服务器,您将收到 link 成功。
希望对您有所帮助。