2

Im want to upload an image using Vue.js and Django-rest. And have few problems with it.

Im trying to use put request (as in docs) and FileUploadParser for it, but getting an error:

detail: "Missing filename. Request should include a Content-Disposition header with a filename parameter.

If i make my header like:

'Content-type':'multipart/form-data',
                'filename': 'file'

Django registers request as OPTIONS, not put, so my put function not called.

My serializer:

class ImagesSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Images
        fields = ('image',)

My view:

class ImagesViewSet(APIView):
    parser_classes = (FileUploadParser,)

    def get(self, request):
        images = Images.objects.all()
        serializer = ImagesSerializer(images, many=True)
        return Response(serializer.data)


    def put(self, request, filename, format=None):
        image = request.data['image']

        Images.objects.create(
            image=image
        )
        return Response(status=204)

My Vue.js request:

import axios from 'axios';

export default {
  name: 'App',
  data(){
    return {
        name: '',
        image: '',
        description: '',
        price: '',
        files: false,
        }
    },
    methods: {
        onFileChange(e) {
            console.log('works');
            var files = e.target.files || e.dataTransfer.files;
            if (!files.length)
                return;
            this.createImage(files[0]);
        },
        createImage(file) {
            var image = new Image();
            var reader = new FileReader();
            var vm = this;

            reader.onload = (e) => {
                vm.image = e.target.result;
            };
            reader.readAsDataURL(file);
        },
        createNewProduct(){

        const config = {
            headers: {
                'Content-type':'multipart/form-data',
                'filename': 'file'
            }
        }

        let formData = new FormData();
        formData.append('image', this.image);

        axios.put('http://127.0.0.1:8000/images/',{
            formData
        }, config).then(response => {
            console.log('Success');
            this.$router.push('/')
        }, response => {
            console.log('FAIL');
        });
        } 
    }
}

What im doing wrong, or what did i miss?

Andrej Vilenskij
  • 487
  • 1
  • 7
  • 23

2 Answers2

2

In addition to the Content-Type header, you're going to want to add a content-disposition header, like so:

headers: {
    'Content-type':'multipart/form-data',
    'Content-Disposition': 'attachment; filename=file',
    'filename': 'file'
}
AlTheOne
  • 105
  • 5
ifiore
  • 451
  • 2
  • 7
  • 19
  • Same problem: even with Content-Disposition request registers as Options – Andrej Vilenskij Apr 11 '19 at 09:07
  • Not sure if Nancy Mooree already answered your question, but the OPTIONS request is a standard request before a PUT/POST request. It's called the preflight request to prevent CORS forgery, which you can read more on here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS That being said, I would try the request once more but remove your 'filename' key. Try `headers: { 'Content-Type':'multipart/form-data', 'Content-Disposition': 'attachment; filename=file' }` Hopefully, that should work. – ifiore Apr 11 '19 at 13:28
  • Once the OPTIONS request is responded to, the browser will then send the PUT request automatically. This should be handled by djangorestframework and shouldn't require you to handle OPTIONS requests at all. – ifiore Apr 11 '19 at 13:31
1

File uploading in Django REST framework is the same with uploading files in multipart/form in django.

To test it you can use curl:

curl -X POST -H "Content-Type:multipart/form-data" -u {username}:{password} \
-F "{field_name}=@{filename};type=image/jpeg" http://{your api endpoint}

You can try solution find here on stackoverflow

link

Nancy Moore
  • 2,322
  • 2
  • 21
  • 38