4

I am doing a File upload test with Django REST.
Python3.6.2
Django1.11
djangorestframework==3.6.4
Excel-OSX 15.38(170902)
OSX 10.12.6

It used to be done successfully with ordinary photo files.
This time is Excel file from website. Here is my testcase copy from references.

 def test_upload_and_process_data_complete_case(self):
        from django.core.files import File
        from django.core.files.uploadedfile import SimpleUploadedFile
        from soken_web.apps.imported_files.models import ImportFile

        file = File(open(str(settings.BASE_DIR) + '/apps/zipcodes/complete.xlsx'))
        uploaded_file = SimpleUploadedFile('new_image.xlsx', file.read(), content_type='multipart/form-data')

        data = {
            'attribute': {'author': 'Sigh'},
            'type': ImportFile.FileType.zipcode,
            'file': uploaded_file
        }
        response = self.client.post(reverse('api:import_file-list'), data, format='multipart')
        response.render()

        self.assertEqual(status.HTTP_201_CREATED, response.status_code)

Like a copy cat. Except this time I download a mock file from https://www.mockaroo.com/.

Here is the error raises when I execute file.read()

file
<File: /Users/el/Code/norak-cutter/soken/soken-web/soken_web/apps/zipcodes/complete.xlsx>
file.read()
Traceback (most recent call last):
  File "/Users/el/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/172.3968.37/PyCharm.app/Contents/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
  File "/Users/el/.pyenv/versions/3.6.2/lib/python3.6/codecs.py", line 321, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb9 in position 14: invalid start byte

Confirmations:
1. I can upload file from my web browser
2. I can open that file without any warning messages.

Question:
Are there anything I forgot to concern?

References:
How can I test binary file uploading with django-rest-framework's test client?
Django REST UnitTest No file was submitted

joe
  • 8,383
  • 13
  • 61
  • 109

1 Answers1

6

The default mode of opening files is "r" which means non-binary read. Python is assuming your file is a text (encoded) file and trying to decode the contents. But it isnt a text file - it's a binary data file.

Change:

open(str(settings.BASE_DIR) + '/apps/zipcodes/complete.xlsx')

to:

open(str(settings.BASE_DIR) + '/apps/zipcodes/complete.xlsx', 'rb')

and it will probably work.

Tom Dalton
  • 6,122
  • 24
  • 35
  • AssertionError: Test data contained a dictionary value for key 'attribute', but multipart uploads do not support nested data. You may want to consider using format='json' in this test case. – joe Sep 29 '17 at 14:21
  • That's a different problem... Since i'm feeling charitible you should probably look at https://stackoverflow.com/a/11170472/2372812 – Tom Dalton Sep 29 '17 at 14:25
  • I had tried copy the content inside and paste with my Excel on OSX. I got different number instead of `0xb9` to be `0x8e`.... – joe Sep 29 '17 at 14:27
  • You seem to have a different problem now. I'd appreciate you accepting my answer and opening a new question for your new problem :) – Tom Dalton Sep 29 '17 at 14:28
  • Thank you very much for your effort. But If I accept your answer. What is the question of my next question? It will be duplicated one. – joe Sep 29 '17 at 14:35
  • "What is the question of my next question?". Indeed. – Tom Dalton Sep 29 '17 at 14:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155607/discussion-between-sarit-and-tom-dalton). – joe Sep 29 '17 at 14:39
  • Thanks for the offer, but I'm done with this question. You should open a new question if you have a new problem. – Tom Dalton Sep 29 '17 at 14:39
  • Thank you very much. The Excel file must be uploaded according to the official docs. I have no idea why upload file has many way to do. I use this `with open(str(settings.BASE_DIR) + '/apps/zipcodes/complete.xlsx', 'rb') as uploaded_file:` – joe Sep 29 '17 at 14:50