django rest框架不接受blob图片文件(不允许文件扩展名“") [英] django rest framework doesn't accept blob picture file (File extension “” is not allowed)

查看:63
本文介绍了django rest框架不接受blob图片文件(不允许文件扩展名“")的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过发出一个包含png blob图像文件的 multipart/form-data 放置请求(从我的Vue前端使用axios)更新用户配置文件.我收到错误消息:不允许使用文件扩展名".这是Userprofile模型上的File字段:

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,
)

这些是我在Userprofile模型中用于保存和更新模型的信号.

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()

我认为可能是由于这些或Userprofile模型所特有的其他原因导致产生错误,因为在另一个模型上,文件上载按预期工作了,尽管我是在发布而不是发出请求.Userprofile模型通过一对一字段连接到用户.

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.

图像是随put请求发送的formdata...可能是这里有些错误:

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

发出请求的axios代码:

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)
  }
}

这是我裁剪图片的部分,它是dataURI,然后我将其转换为Blob以发送到后端服务器:

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')

推荐答案

由于端点需要特定的文件扩展名,因此您必须手动设置它,因为blob没有文件名,并且用于文件上载的默认值为 blob .FormData.append中有第三个可选参数来设置文件名

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')

这篇关于django rest框架不接受blob图片文件(不允许文件扩展名“")的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆