问题
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:
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