图片:[“未提交任何文件。”]角度6?尝试过DRF图像和文件字段

时间:2018-12-27 10:15:30

标签: django angular amazon-web-services amazon-s3 django-rest-framework

这是我将文件上传到s3的代码。 现在我将其保存在本地

class UploadedImage(models.Model):
    image = models.ImageField("Uploaded image", upload_to=scramble_uploaded_filename)
    thumbnail = models.ImageField("Thumbnail of uploaded image", blank=True)
    title = models.CharField("Title of the uploaded image", max_length=255, default="Unknown Picture")
    description = models.TextField("Description of the uploaded image", default="")
    def __str__(self):
        return self.title
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        self.thumbnail = create_thumbnail(self.image)
        super(UploadedImage, self).save(force_update=force_update)

下面是我的序列化器

class UploadedImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = UploadedImage
        fields = ('pk', 'image', 'thumbnail', 'title', 'description', )
        read_only_fields = ('thumbnail',)

和观看次数

class UploadedImagesViewSet(viewsets.ModelViewSet):
    queryset = UploadedImage.objects.all()
    serializer_class = UploadedImageSerializer

这工作正常,但是在角度6中集成api时出现错误。

下面的角度为6 ts和html的代码

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders} from '@angular/common/http';
import { Router } from '@angular/router';
import { ViewChild } from '@angular/core';
@Component({
  selector: 'app-photo-upload',
  templateUrl: './photo-upload.component.html',
  styleUrls: ['./photo-upload.component.css']
})
export class PhotoUploadComponent implements OnInit {
  @ViewChild("fileInput") fileInput;
  constructor(private http: HttpClient ,private router: Router) { }
  ngOnInit() {
  }


  url: string | ArrayBuffer;
  onSelectFile(event) { // called each time file input changes
    if (event.target.files && event.target.files.length>0) {
      console.log(event.target.files[0]);
      var reader = new FileReader();

      reader.readAsDataURL(event.target.files[0]); // read file as data url

      reader.onload = () => { // called once readAsDataURL is completed
        this.url = reader.result;
        console.log(this.url);


      }
    }

  }
  photoupload(f){
    this.onSelectFile(event)
    f.value.images=this.url
    console.log(f.value)

    const header = new HttpHeaders({'Content-Type': 'application/json'});
    this.http.post('http://11.111.11.111:8000/api/images/',
      f.value,{headers:header}).subscribe(( data )  =>  
        { console.log(data)   
        this.router.navigate(['../dashboard']);
         }
        ,error => {console.log(error);
        })
  }
}

hmtl文件

<form (ngSubmit)="photoupload(list)" #list="ngForm" >
    <div class="container">
        <label for="title"><b>Photo Title</b></label>
        <input type="text" name="title" placeholder="Enter Title" value="title" id="title" [(ngModel)]= "title"  required >
        <label for="discription"><b>Photo Description</b></label><br>
        <input type="text" placeholder="Enter Description" name="discription"  [(ngModel)]= "discription" required>
        <label for="image"><b>Image </b></label> &nbsp;
        <input type="file" name="image"  (change)="onSelectFile($event)" required ><br>
      <button  type="submit">Upload Photo </button>
    </div>
    <div class="container" style="background-color:#f1f1f1">
    </div>
  </form>

现在我的问题是我的api在邮递员中工作,但我无法将其集成到angular 6上,这是与angular base 64 image有关的问题? 但是我也能够生成URL,我所能做的就是将这些数据从前端发送到后端

错误图片 problem image

1 个答案:

答案 0 :(得分:0)

您正在使用Angular6前端调用API终结点时将Base64数据发送到后端。在这种情况下,您必须更新序列化程序并实现此类功能,以便它可以获取Base64数据并生成映像文件以保存在服务器上。

更新您的 UploadedImageSerializer ,如下所示

from rest_framework import serializers

class Base64ImageField(serializers.ImageField):
"""
A Django REST framework field for handling image-uploads through raw post data.
It uses base64 for encoding and decoding the contents of the file.

Heavily based on
https://github.com/tomchristie/django-rest-framework/pull/1268

Updated for Django REST framework 3.
"""

    def to_internal_value(self, data):
        from django.core.files.base import ContentFile
        import base64
        import six
        import uuid

        # Check if this is a base64 string
        if isinstance(data, six.string_types):
            # Check if the base64 string is in the "data:" format
            if 'data:' in data and ';base64,' in data:
                # Break out the header from the base64 content
                header, data = data.split(';base64,')

            # Try to decode the file. Return validation error if it fails.
            try:
                decoded_file = base64.b64decode(data)
            except TypeError:
                self.fail('invalid_image')

            # Generate file name:
            file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
            # Get the file name extension:
            file_extension = self.get_file_extension(file_name, decoded_file)

            complete_file_name = "%s.%s" % (file_name, file_extension, )

            data = ContentFile(decoded_file, name=complete_file_name)

        return super(Base64ImageField, self).to_internal_value(data)

    def get_file_extension(self, file_name, decoded_file):
        import imghdr

        extension = imghdr.what(file_name, decoded_file)
        extension = "jpg" if extension == "jpeg" else extension

        return extension

class UploadedImageSerializer(serializers.ModelSerializer):
    image = Base64ImageField(
        max_length=None, use_url=True,
    )

    class Meta:
        model = UploadedImage
        fields = ('pk', 'image', 'thumbnail', 'title', 'description', )
        read_only_fields = ('thumbnail',)

注意:此处的“缩略图”字段可能会引起问题。我将尽快更新此答案。

有关更多信息,请参阅Original Post