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')
我正在尝试通过发出包含 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')