django rest framework не принимает файл изображения большого двоичного объекта (расширение файла «» не допускается) - PullRequest
1 голос
/ 03 августа 2020

Я пытаюсь обновить профиль пользователя, сделав запрос multipart / form-data put (из моего vue внешнего интерфейса с использованием ax ios), содержащий файл изображения blob в формате png. Я получаю сообщение об ошибке: Расширение файла «» недопустимо. Это поле файла в модели профиля пользователя:

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

Это сигналы, которые я использую в модели профиля пользователя для сохранить и обновить модель.

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

Я думаю, что это может быть из-за этих или каких-то других спецификаций c модели Userprofile, которая создает ошибку, потому что на другой модели загрузка файла работает, как задумано, хотя там я делаю сообщение, а не запрос на размещение. Модель Userprofile связана с пользователем с помощью поля «один к одному».

В моем сериализаторе или представлениях нет ничего особенного, что могло бы вызвать ошибку.

Я не знаю, что я мог бы сделать, чтобы исправить это. Спасибо за все советы. Если вам нужна другая информация, не стесняйтесь спрашивать.

Изображение - это данные формы, отправленные с запросом на размещение ... возможно, там что-то не так:

1

Код ax ios, который делает запрос:

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

1 Ответ

0 голосов
/ 03 августа 2020

Поскольку для вашей конечной точки требуется конкретное c расширение имени файла, вам придется установить его вручную, потому что у больших двоичных объектов нет имен файлов, а значение по умолчанию, используемое для загрузки файла, - blob. В FormData.append есть третий необязательный параметр для установки имени файла

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