最近在做图片上传功能遇到不少坑,再此记录避免大家少踩坑。
百度FileTransfer文件上传没有一个完整的前后端栗子,这里前后端都记录下,后端采用WCF
废话就不多说了直接上代码
前端
1. CameraServiceProvider.ts 这是一个服务
/**
* 打开相机,返回文件路径
*/
openCamera(cameraOptions: any): Promise<any> {
return new Promise((resolve, reject) => {
const options: CameraOptions = cameraOptions;
this.camera.getPicture(options).then((imageData) => {
console.log("got file: " + imageData);
// If it's base64:
imageData = 'data:image/jpeg;base64,' + imageData;
resolve(imageData);
}, (err) => {
// Handle error
reject(err);
});
});
}
2. 上传页面
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, ToastController, LoadingController, Loading } from 'ionic-angular';
import { PhotoViewer } from '@ionic-native/photo-viewer';
import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer';
import { File } from '@ionic-native/file';
import { Camera } from '@ionic-native/camera';
import { MyApp } from '../../app/app.component';
import { CameraServiceProvider } from '../../providers/camera-service/camera-service';
import { SqliteServiceProvider } from '../../providers/sqlite-service/sqlite-service';
/**
* Generated class for the InspectionPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
@IonicPage()
@Component({
selector: 'page-inspection',
templateUrl: 'inspection.html',
})
export class InspectionPage {
item: any;
username: string;
ID: any;
CheckValue: any;
Remark: any;
loading: Loading;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
private camera: Camera,
private file: File,
private transfer: FileTransfer,
private photoViewer: PhotoViewer,
private toastCtrl: ToastController,
private loadingCtrl: LoadingController,
private sqliteService: SqliteServiceProvider,
private cameraService: CameraServiceProvider
) {
}
/**打开相册 */
openAlbum() {
var options = {
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
saveToPhotoAlbum: false,
correctOrientation: true
};
this.getImage(options);
}
/**打开相机 */
openCamera() {
var options = {
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
sourceType: this.camera.PictureSourceType.CAMERA,
saveToPhotoAlbum: false,
correctOrientation: true
};
this.getImage(options);
}
clickImage(item: any) {
this.photoViewer.show(item, '图片预览');
}
getImage(options) {
this.cameraService.openCamera(options).then((imagePath) => {
this.uploadImage(imagePath);
}, (err) => {
this.presentToast('Error while selecting image.');
});
}
// 上传图像
public uploadImage(newFileName: any) {
let url: string = MyApp.getCurrentUrl() + "/system/api/tubescanning.svc/SaveImage";
var targetPath = this.pathForImage(newFileName);
var options = {
fileKey: "imgfile",
fileName: newFileName,
httpMethod: 'POST',
mimeType: "image/jpeg'",
params: {}
};
const fileTransfer: FileTransferObject = this.transfer.create();
this.loading = this.loadingCtrl.create({
content: '正在上传...',
cssClass: 'loadingwrapper'
});
this.loading.present();
// 使用文件传输上传图像
fileTransfer.upload(targetPath, url, options).then(data => {
this.loading.dismissAll()
alert(JSON.stringify(data));
this.presentToast('图像上传成功.');
}, err => {
this.loading.dismissAll()
this.presentToast('图像上传失败.');
});
}
//为图像创建新名称
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
private presentToast(text) {
let toast = this.toastCtrl.create({
message: text,
duration: 3000,
position: 'top'
});
toast.present();
}
}
3. 后端
[OperationContract]
[WebInvoke(UriTemplate = "SaveImage", Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
public string SaveImage()
{
try
{
HttpPostedFile file = HttpContext.Current.Request.Files["imgfile"];
if (file == null)
return null;
string targetFilePath = AppDomain.CurrentDomain.BaseDirectory + file.FileName;
file.SaveAs(targetFilePath);
return file.FileName.ToString();
}
catch (Exception e)
{
return e.Message.ToString();
}
}
到这里遇到一个问题上传图片会遇到 在调用 HttpRequest.GetBufferlessinputStream 之后,此方法或属性不受支持错误,百度老半天查不到问题所在,实在没办法用了Google最后发现需要使用Module在WCF根目录下创建WcfReadEntityBodyModeWorkaroundModule.cs类该类继承IHttpModule
3.1 这是解决办法地址
3.2 接下来直接上代码
public class WcfReadEntityBodyModeWorkaroundModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
}
void context_BeginRequest(object sender, EventArgs e)
{
//This will force the HttpContext.Request.ReadEntityBody to be "Classic" and will ensure compatibility..
Stream stream = (sender as HttpApplication).Request.InputStream;
}
}
3.3 Web.config 也需要加入如下配置
<appSettings>
<add key="wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode" value="true" />
</appSettings>
到这里算是解决了上述问题这时候可以上传小文件在上传大文件的时候还是会报错。这是因为上传有限制大小在Web.config的system.serviceModel加入如下配置
<bindings>
<webHttpBinding>
<binding maxBufferPoolSize="5242880000" maxBufferSize="655360000" maxReceivedMessageSize="655360000">
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
需要注意的是需要和服务.svc进行绑定如图:
OK到此大功告成。结束!!!