我开发了一个Angular应用程序,用户可以在其中处理品牌。
创建/更新品牌时,用户还可以上传徽标。所有数据都通过使用Django REST Framework构建的REST API发送到DB。
使用Django REST Framework API网站我可以上传文件,但是当我通过API发送数据时使用Angular我收到错误。 我还尝试使用FileReader将File对象编码为base64,但是我从Django得到了同样的错误。
你能帮我理解这个问题吗?
模型:
export class Brand {
id: number;
name: string;
description: string;
is_active: boolean = true;
is_customer_brand: boolean = false;
logo_img: Image;
}
export class Image {
id: number;
img: string; // URL path to the image (full size)
img_md: string; // medium size
img_sm: string; // small
img_xs: string; // extra-small/thumbnail
}
服务:
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Brand } from './brand';
const endpoint = 'http://127.0.0.1:8000/api/brands/'
@Injectable()
export class BrandService {
private brands: Array<Brand>;
constructor(private http: Http) { }
list(): Observable<Array<Brand>> {
return this.http.get(endpoint)
.map(response => {
this.brands = response.json() as Brand[];
return response.json();
})
.catch(this.handleError);
}
create(brand: Brand): Observable<Brand> {
console.log(brand);
return this.http.post(endpoint+'create/', brand)
.map(response => response.json())
.catch(this.handleError);
}
get(id): Observable<Brand> {
return this.http.get(endpoint+id)
.map(response => response.json())
.catch(this.handleError);
}
private handleError(error:any, caught:any): any {
console.log(error, caught);
}
}
浏览器控制台出错:
“{”logo_img“:{”img“:[”提交的数据不是文件。检查 表单上的编码类型。“]}}”
Django Serializer :
class BrandSerializer(ModelSerializer):
is_active = BooleanField(required=False)
logo_img = ImageSerializer(required=False, allow_null=True)
class Meta:
model = Brand
fields = [
'id',
'name',
'description',
'is_active',
'is_customer_brand',
'logo_img',
]
def update(self, instance, validated_data):
image = validated_data.get('logo_img',None)
old_image = None
if image:
image = image.get('img',None)
brand_str = validated_data['name'].lower().replace(' ','-')
ext = validated_data['logo_img']['img'].name.split('.')[-1].lower()
filename = '{0}.{1}'.format(brand_str,ext)
user = None
request = self.context.get('request')
if request and hasattr(request, 'user'):
user = request.user
image_serializer_class = create_image_serializer(path='logos', filename=filename, created_by=user, img_config = {'max_w':3000.0,'max_h':3000.0,'max_file_size':1.5,'to_jpeg':False})
image_serializer = image_serializer_class(data=validated_data['logo_img'])
image_serializer.is_valid()
validated_data['logo_img'] = image_serializer.save()
old_image = instance.logo_img
super(BrandSerializer, self).update(instance,validated_data)
if old_image: # Removing old logo
old_image.img.delete()
old_image.img_md.delete()
old_image.img_sm.delete()
old_image.img_xs.delete()
old_image.delete()
return instance
def create(self, validated_data):
image = validated_data.get('logo_img',None)
print(image)
if image:
print(image)
image = image.get('img',None)
print(image)
brand_str = validated_data['name'].lower().replace(' ','-')
ext = validated_data['logo_img']['img'].name.split('.')[-1].lower()
filename = '{0}.{1}'.format(brand_str,ext)
user = None
request = self.context.get('request')
if request and hasattr(request, 'user'):
user = request.user
image_serializer_class = create_image_serializer(path='logos', filename=filename, created_by=user, img_config = {'max_w':3000.0,'max_h':3000.0,'max_file_size':1.5,'to_jpeg':False})
image_serializer = image_serializer_class(data=validated_data['logo_img'])
image_serializer.is_valid()
validated_data['logo_img'] = image_serializer.save()
return super(BrandSerializer, self).create(validated_data)
答案 0 :(得分:0)
使用文件向服务器发布新品牌时,我有三个主要选择:
Base64编码将涉及不可接受的有效负载。 所以我选择使用multipart / form-data。
以下是我在Angular服务中实现的方法:
create(brand: Brand): Observable<Brand> {
let headers = new Headers();
let formData = new FormData(); // Note: FormData values can only be string or File/Blob objects
Object.entries(brand).forEach(([key, value]) => {
if (key === 'logo_img') {
formData.append('logo_img_file', value.img);
} else {
formData.append(key, value);
});
return this.http.post(endpoint+'create/', formData)
.map(response => response.json())
.catch(this.handleError);
}
重要说明:由于无法使用FormData
嵌套字段,因此我无法附加formData.append('logo_img', {'img' : FILE_OBJ })
。我更改了API,以便在名为logo_img_file
的一个字段中接收文件。
希望我的问题对某人有所帮助。