我无法在我的角度/节点应用中找到正确方向的照片。
我的应用程序设置为使用ng2-file-upload将文件从角度应用程序发送到服务器,其中multer和multer-s3将该照片保存在AWS S3中。然后我将文件名保存在我的postgres数据库中,并使用它通过url调用照片。
我的问题是,照片是由iPhone上传的(可能是其他人我只试过iphone)并且向左旋转。
我在服务器端调查了不适用于我的不同选项。这包括库fix-orientation和jpeg-autorotate。
是否有人在Angular2 +的客户端实施了解决方案?
这是我在服务器端的图片上传代码
aws.config.loadFromPath(path3);
var s3 = new aws.S3();
var fileName = '';
var uploadM = multer({
storage: multerS3({
s3: s3,
bucket: 'XXX',
acl: 'public-read',
metadata: function (req, file, cb) {
console.log(file);
console.log(req.file);
cb(null, {fieldName: file.fieldname});
},
key: function (req, file, cb) {
fileName = Date.now().toString() + "-" + (Math.round(Math.random() * 10000000000000000)).toString() + '-' + file.originalname;
cb(null, fileName)
}
})
});
router.post('/upload', uploadM.array('photo', 3), function(req,res) {
if (res.error) {
return res.status(400).json({
message: "Error",
error: res.error
});
}
return res.status(200).send(fileName);
});
module.exports = router;
这是我在角度应用上的代码
public uploader:FileUploader = new FileUploader({url: this.devUrl, itemAlias: 'photo'});
constructor(
private userS: UserService,
private authS: MyAuthService,
private router: Router,
private itemS: ItemService,
private uis: UiService) {}
ngOnInit() {
this.uploader.onAfterAddingFile = (file)=> { file.withCredentials = false; };
this.uploader.onCompleteItem = (item:any, response:any, status:any, headers:any) => {
this.awsUrls.push('AWSURL' + response);
this.filesUploaded = true;
this.uploaderLoading = false;
};
}
addItem() {
this.uploaderLoading = true;
this.itemS.onNewItem(this.awsUrls)
.subscribe(data => {
this.uis.onFlash('Posted Successfully. Add Details!', 'success');
this.itemS.onSetUpdateItemId(data.id, false);
this.uploaderLoading = false;
this.onPhotoAdded();
}, resp => {
this.uploaderLoading = false;
this.uis.onFlash('Error Posting', 'error');
console.log(resp);
});
}
onUploadClicked() {
this.uploader.uploadAll();
this.uploaderLoading = true;
}
答案 0 :(得分:3)
安装exif-js
npm i exif-js --save
将EXIF导入您的组件
import * as EXIF from 'exif-js';
setImgOrientation方法具有文件 参数,该参数是上传的文件对象, inputBase64String 将同一文件的 base64 字符串
setImgOrientation(file, inputBase64String) {
return new Promise((resolve, reject) => {
const that = this;
EXIF.getData(file, function () {
if (this && this.exifdata && this.exifdata.Orientation) {
that.resetOrientation(inputBase64String, this.exifdata.Orientation, function
(resetBase64Image) {
inputBase64String = resetBase64Image;
resolve(inputBase64String);
});
} else {
resolve(inputBase64String);
}
});
});
}
resetOrientation(srcBase64, srcOrientation, callback) {
const img = new Image();
img.onload = function () {
const width = img.width,
height = img.height,
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// set proper canvas dimensions before transform & export
if (4 < srcOrientation && srcOrientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// transform context before drawing image
switch (srcOrientation) {
case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, height, width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
default: break;
}
// draw image
ctx.drawImage(img, 0, 0);
// export base64
callback(canvas.toDataURL());
};
img.src = srcBase64;
}
答案 1 :(得分:1)
在我的观点中,理想的解决方案是在将图像发送到S3之前旋转图像,使其仅完成一次(并非每次用户观看图像时)。
您可以在上传到S3之前使用this librairy,以确保图片处于核心方向。
看看this sample,它可以很容易地集成到您的代码中。
此致
答案 2 :(得分:1)
如果所有 iPhone图像始终,您可以在postgres表格中找到一个名为iphone
的列,并在从上传照片时将其设置为true iPhone然后使用CSS
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-ms-transform: rotate(90deg);
-o-transform: rotate(90deg);
transform: rotate(90deg);
答案 3 :(得分:0)
搞乱了几个JS库和基于JS的修复程序。我特别需要在Angular 4中修复图像方向。这是我实现的一种解决方法,可以帮助Angular开发人员搜索答案。
基本上,我在上传过程中添加了输入,询问用户该设备是iPhone还是iPhone风景照片。在我的模型中使用iPhone
和iPhoneLandscape
布尔值时,如果用户指示照片是使用任一参数拍摄的,我会将这些变量设置为true。
在客户端,我检索了项目照片,如果item.iPhone为真,则使用ngStyle将照片旋转90度,如果item.iPhoneLandscape为真,则使用180度旋转照片。
//对于postgres用户....我的项目模型item.mode.js
module.exports = function(sequelize, DataTypes) {
var Item = sequelize.define("Item", {
photos: {
type: DataTypes.ARRAY(DataTypes.STRING),
allowNull: false
},
name: {
type: DataTypes.STRING,
isLowerCase: true,
allowNull: true,
defaultValue: null
},
description: {
type: DataTypes.STRING,
isLowerCase: true,
allowNull: true,
defaultValue: null
},
condition: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null
},
price: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null
},
interval: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 1
},
category: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null
},
negotiable: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: true
},
shipping: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false
},
freeShipping: DataTypes.BOOLEAN,
length: DataTypes.INTEGER,
width: DataTypes.INTEGER,
height: DataTypes.INTEGER,
weight: DataTypes.INTEGER,
unavailableDates: {
type: DataTypes.ARRAY(DataTypes.RANGE(DataTypes.DATE)),
allowNull: true,
defaultValue: []
},
available: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: true
},
securityDeposit: {
type: DataTypes.INTEGER,
defaultValue: 0
},
iPhone: {
type: DataTypes.BOOLEAN,
defaultValue: false
},
iPhoneLandscape: {
type: DataTypes.BOOLEAN,
defaultValue: false
}
});
//我的模型在angular item.model.ts
上export class Item {
constructor(
public id?: number,
public photos?: string[],
public name?: string,
public description?: string,
public condition?: string,
public price?: number,
public interval?: number,
public category?: string,
public negotiable?: boolean,
public shipping?: boolean,
public length?: number,
public width?: number,
public height?: number,
public weight?: number,
public unavailableDates?: Date[],
public available?: boolean,
public iPhone?: boolean,
public iPhoneLandscape?: boolean,
public ownerId?: number,
public owner?: object
) {}
}
//在我的item.service.ts
中从服务器调用该项目 onReturnItems() {
return this.http.get(this.devUrl)
.map(data => {
let items: Item[] = data['obj'];
return items;
})
.shareReplay();
}
//我的样式函数调用item-list.component.ts中的CSS对象
styleObject(s: string, item): Object {
if (s === 'photo') {
if (item.iPhone) {
return {'-webkit-transform': 'rotate(90deg)',
'-moz-transform': 'rotate(90deg)',
'-ms-transform': 'rotate(90deg)',
'-o-transform': 'rotate(90deg)',
'transform': 'rotate(90deg)'}
} else if (item.iPhoneLandscape) {
return {'-webkit-transform': 'rotate(180deg)',
'-moz-transform': 'rotate(180deg)',
'-ms-transform': 'rotate(180deg)',
'-o-transform': 'rotate(180deg)',
'transform': 'rotate(180deg)'}
}
}
//最后在item-list.component.html
的模板中使用ngStyle和ngFor<div class="card column is-one-quarter" style="padding: 0; margin-left: 12px; margin-right: 12px;" *ngFor="let item of items">
<div class="card-image" (click)="onSetItemId(item.id)">
<!--<iframe [src]="item.photos[0]"></iframe>-->
<figure class="image" style="border-radius: 0;">
<img [src]="item.photos[0]" alt="Image" [ngStyle]="styleObject('photo', item)" *ngIf="itemsRetrieved" style="border-radius: 0;">
</figure>
</div>
希望你能从中解决这个问题!祝你好运!