django rest 框架不接受 blob 图片文件(不允许文件扩展名“”)

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

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

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

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

@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 模型的原因造成了错误,因为在另一个模型上文件上传按预期工作,尽管我正在制作 post 而不是提出要求。 Userprofile 模型通过一对一字段连接到用户。

在我的序列化程序或视图中没有什么特别之处可能导致错误。

我不知道我能做些什么来解决这个问题。感谢您的所有建议。如果您需要任何其他信息,请随时询问。

图像是随 put 请求一起发送的表单数据...可能有问题:

发出请求的axios代码:

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 以发送到后端服务器:


  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中还有第三个可选参数设置一个文件名

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