django rest framework doesn't accept blob picture file (File extension “” is not allowed)

允我心安 提交于 2021-01-28 02:15:46

问题


I am trying to update a User Profile by making a multipart/form-data put request (from my vue frontend using axios) containing a png blob image file. I receive an error message: File extension “” is not allowed. This is the File Field on the Userprofile Model:

    profile_picture = models.FileField(
    _("Profile Pictures"),
    upload_to="profile_picture",
    max_length=100,
    blank=True,
    null=True,
)

These are the signals I use in the Userprofile model to save and update the Model.

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

I think it may be because of these or something other specific to the Userprofile model that creates the error because on another model the file upload works as intended, although there I am making a post and not a put request. The Userprofile model is connected to the User by a One to One Field.

Ther is nothing special in my serializer or views that could be causing the bug.

I have no Idea what I could do to fix this. Thanks for all advice. If you need any other information feel free to ask.

The image is the formdata sent with the put request... maybe somethings wrong there:

1

The axios code that makes the request:

import axios from 'axios'

const apiClient = axios.create({
  baseURL: `http://127.0.0.1:8000/`,
  withCredentials: false,
  headers: {
    Accept: 'application/json',
    'Content-Type': 'multipart/form-data'
  }
})

export default {
  updateUser(pk, params) {
    return apiClient.put('/users/' + pk + '/', params)
  }
}

This is the part where I crop a picture and it is a dataURI which I then convert to a blob to send to the backend server:


  methods: {
    crop() {
      const { coordinates, canvas } = this.$refs.cropper.getResult()
      this.coordinates = coordinates
      this.file = canvas.toDataURL()
    },
    uploadImage(event) {
      const input = event.target
      if (input.files && input.files[0]) {
        // create a new FileReader to read this image and convert to base64 format
        const reader = new FileReader()
        // Define a callback function to run, when FileReader finishes its job
        reader.onload = (e) => {
          // Read image as base64 and set to imageData
          this.file = e.target.result
        }
        // Start the reader job - read file as a data url (base64 format)
        reader.readAsDataURL(input.files[0])
      }
    },
    dataURItoBlob(dataURI) {
      // convert base64 to raw binary data held in a string
      const byteString = atob(dataURI.split(',')[1])

      // separate out the mime component
      const mimeString = dataURI
        .split(',')[0]
        .split(':')[1]
        .split(';')[0]

      // write the bytes of the string to an ArrayBuffer
      const ab = new ArrayBuffer(byteString.length)
      const ia = new Uint8Array(ab)
      for (let i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i)
      }
      return new Blob([ab], { type: mimeString })
    },
    async updateUser() {
      this.crop()
      delete this.user.password2
      const formData = new FormData()
      if (this.file)
        formData.append('profile_picture', this.dataURItoBlob(this.file))
      if (this.user.username) formData.append('username', this.user.username)
      else formData.append('username', this.$auth.user.username)
      if (this.user.email) formData.append('email', this.user.email)
      if (this.user.bio) formData.append('bio', this.user.bio)
      if (this.user.password) formData.append('password', this.user.password)
      else formData.append('password', this.$auth.user.password)

      await UserFormService.updateUser(this.$auth.user.pk, formData)

      await this.$store.dispatch('users/updateUser', this.user)
      this.$auth.setUser(this.$store.state.users.user)
      this.$router.push('/users/me')


回答1:


Since your endpoint requires a specific file name extension you will have to set it manually because blobs do not have file names and the default used for a file upload is blob. There is a third optional parameter in FormData.append to set a file name

formData.append('profile_picture', this.dataURItoBlob(this.file), 'some_filename.valid_extension')


来源:https://stackoverflow.com/questions/63230458/django-rest-framework-doesnt-accept-blob-picture-file-file-extension-is-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!