def test_multipart_non_text_file(self):
        stmt = {"actor":{"mbox":"mailto:tom@example.com"},
            "verb":{"id":"http://tom.com/verb/butted"},
            "object":{"id":"act:tom.com/objs/heads"},
            "attachments": [
            {"usageType": "http://example.com/attachment-usage/test",
            "display": {"en-US": "A test picture"},
            "description": {"en-US": "A test picture (description)"},
            "contentType": "image/png",
            "length": 27,
            "sha2":""}]}

        message = MIMEMultipart(boundary="myboundary")
        img_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'adl_lrs','static','img', 'example.png'))
        img = open(img_path, 'rb')
        img_data = img.read()
        img.close()
        imgsha = hashlib.sha256(img_data).hexdigest()
        stmt['attachments'][0]["sha2"] = str(imgsha)
        
        stmtdata = MIMEApplication(json.dumps(stmt), _subtype="json", _encoder=json.JSONEncoder)
        imgdata = MIMEImage(img_data)

        imgdata.add_header('X-Experience-API-Hash', imgsha)
        imgdata.replace_header('Content-Transfer-Encoding', 'binary')
        imgdata.set_payload(img_data)

        message.attach(stmtdata)
        message.attach(imgdata)

        r = self.client.post(reverse('lrs:statements'), message.as_string(),
            content_type='multipart/mixed', Authorization=self.auth, X_Experience_API_Version=settings.XAPI_VERSION)
        self.assertEqual(r.status_code, 200)
        
        param= {"attachments":True}
        path = "%s?%s" + (reverse('lrs:statements'),urllib.urlencode(param))
        r = self.client.get(path, X_Experience_API_Version=settings.XAPI_VERSION, Authorization=self.auth)
        self.assertEqual(r.status_code, 200)
        self.assertEqual(r['Content-Type'], 'multipart/mixed; boundary=======ADL_LRS======')
        # Have to add the header to the top of the body else the email lib won't parse it correctly
        msg = message_from_string("Content-Type:multipart/mixed; boundary=======ADL_LRS======" + r.content)
        self.assertTrue(msg.is_multipart())

        parts = []
        for part in msg.walk():
            parts.append(part)
  
        self.assertEqual(parts[1]['Content-Type'], "application/json")
        self.assertTrue(isinstance(json.loads(parts[1].get_payload()), dict))
        # MIMEImage automatically b64 encodes data to be transfered
        self.assertEqual(parts[2].get_payload(), img_data)
        self.assertEqual(parts[2].get("X-Experience-API-Hash"), imgsha)
        self.assertEqual(imgsha, hashlib.sha256(parts[2].get_payload()).hexdigest())
        self.assertEqual(parts[2].get('Content-Type'), 'image/png')
        self.assertEqual(parts[2].get('Content-Transfer-Encoding'), 'binary')
dataset/ETHPy150Open adlnet/ADL_LRS/lrs/tests/test_AttachmentAndSigned.py/AttachmentAndSignedTests.test_multipart_non_text_file/operator `%` -> `+`