本人是ionic框架的一名小白,之前用ionic3做项目。项目做了一半之后停做了一段时间,现在继续开始。但是发现,ionic已经升级到了ionic4版本,但ionic4跟ionic3差别还挺大的,所以我还是选择用熟悉的ionic3来接着做项目。
最近,身为小白的我在研究怎么在手机上选择文件并且上传,想到了两个思路,一个是用HTML上的:
这是HTML的经典方法,但是本人用这个方法获取了文件之后就不会怎么上传了。查了一下大佬的文章,知道了ionic框架下有个专门的方法上传,就是用filechooser插件获取文件URL,然后用filetransfer来上传。具体方法参见这位大佬的文档:
ionic文件上传
这个文档将过程写的很清楚,但是本人实践的时候,在filechooser这个插件上遇到了极大的难题: 按照官网文档对这个插件的说明:
File Chooser - Ionic Documentation
在命令行的项目根目录用
ionic cordova plugin add cordova-plugin-filechooser
npm install @ionic-native/file-chooser
然后在正文中用
import { FileChooser } from '@ionic-native/file-chooser/ngx';
//别忘了要在providers里面加上FileChooser,后面的FileTransfer同理
constructor(private fileChooser: FileChooser) { }
...
this.fileChooser.open()
.then(uri => console.log(uri))
.catch(e => console.log(e));
uri就是文件在你手机上的绝对路径,然后借助FileTransfer实现上传,要先插入啊,声明啊什么的跟filechooser是一样的。下面是FileTransfer的相关代码内容:
options = {
fileKey: 'file',
fileName: 'name',
params: {name: filename, type: filetype, model: 'file', author: global.username},
headers: {}
}
var reqUri = APP_SERVE_URL + '/postimg'; // APP_SERVE_URL是服务器地址
const fileTransfer: FileTransferObject = this.transfer.create();
fileTransfer.upload(uri, reqUri, options).then((data) => {
alert('上传成功');
}, (err) => {
alert('上传失败');
});
我照做了,然而我遇到了这样的问题,不知道各位有没有:
Object(...) is not a function
发现是filechooser有问题。这个问题,困扰了我好久,难道是filechooser插件的具体内容写错了吗?不可能啊,这可是大神写的啊。我猜应该是版本问题,现在我是ionic3的项目,但是ionic版本是ionic4,出点这个问题很可能是版本的问题。
后来我了解了一下插件的原理,发现问题出在.
\node_modules@ionic-native\file-chooser\ngx\index.js中:
import { Plugin, cordova, IonicNativePlugin } from '@ionic-native/core';
……
FileChooser.prototype.open = function () { return cordova(this, "open", {}, arguments); };
//就是这里cordova(this, "open", {}, arguments)是object(...),因此报错是这里
首先,这里的cordova是小写的,然而在'@ionic-native/core'中只有Cordova,再有,调试后发现Object(...) is not a function说的的确是这里。于是我就改了一下,然后又发现有好多其他问题……比如:
this.filechooser.open().then() i……s not a function
这里说明open函数的格式又有问题。。。
最后,对比着FileOpener2的index.js文件的内容,奋斗了好久,终于将这个官方实例实现了。奋斗过程很复杂,这里就不吐槽了,最后我改对了。
我只是改了\node_modules@ionic-native\file-chooser\ngx\index.js这个文件,现在发给各位分享一下,当然,可能有其他问题,各位发现的话记得私聊:
原来的代码:
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { IonicNativePlugin, cordova } from '@ionic-native/core';
var FileChooserOriginal = /** @class */ (function (_super) {
__extends(FileChooserOriginal, _super);
function FileChooserOriginal() {
return _super !== null && _super.apply(this, arguments) || this;
}
FileChooserOriginal.prototype.open = function () { return cordova(this, "open", {}, arguments); };
FileChooserOriginal.pluginName = "FileChooser";
FileChooserOriginal.plugin = "cordova-plugin-filechooser";
FileChooserOriginal.pluginRef = "fileChooser";
FileChooserOriginal.repo = "https://github.com/ihadeed/cordova-filechooser";
FileChooserOriginal.platforms = ["Android"];
return FileChooserOriginal;
}(IonicNativePlugin));
var FileChooser = new FileChooserOriginal();
export { FileChooser };
现在改为:
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Injectable } from '@angular/core';
import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core';
var FileChooser = /** @class */ (function (_super) {
__extends(FileChooser, _super);
function FileChooser() {
return _super !== null && _super.apply(this, arguments) || this;
}
FileChooser.prototype.open = function () { return Cordova(this, "open", {}, arguments); };
/*FileChooser.pluginName = "FileChooser";
FileChooser.plugin = "cordova-plugin-filechooser";
FileChooser.pluginRef = "fileChooser";
FileChooser.repo = "https://github.com/ihadeed/cordova-filechooser";
FileChooser.platforms = ["Android"];*/
FileChooser.decorators = [
{ type: Injectable },
];
FileChooser.ctorParameters = function () { return []; };
__decorate([
Cordova({
callbackOrder: 'reverse'
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], FileChooser.prototype, "open", null);
FileChooser = __decorate([
Plugin({
pluginName: 'FileChooser',
plugin: 'cordova-plugin-filechooser',
pluginRef: 'fileChooser',
repo: ' https://github.com/ihadeed/cordova-filechooser',
platforms: ['Android']
})
], FileChooser);
return FileChooser;
}(IonicNativePlugin));
export { FileChooser };
将文件替换一下,官方的实例就可以用了。
实际上,这应该是个版本的问题,但是ionic4跟3的差别好像有点大,我不太想去看,所以就在ionic3里面硬改了,如果有哪个道友跟我一样懒,而且遇到了相同的问题,希望能帮助到大家。