【问题标题】:Django Rest - FileUploadView - Unexpected data being added into an Uploaded FileDjango Rest - FileUploadView - 意外的数据被添加到上传的文件中
【发布时间】:2019-08-15 17:49:55
【问题描述】:

这是我的 FileUploadView 类,用于处理上传文件的 POST 请求。我期待的文件是 XML 文件,我在其中使用 ElementTree 在 fileHandler() 中解析它。但是,当使用 Postman 通过 using ('form-data') 发送文件时,我意识到它正在将某种类型的标题附加到我上传的文件中,这反过来又导致 tree parse() 出现语法错误,因为它读取非 XML 格式的内容。

我尝试使用 HTTPie 发送文件,没有问题,XML Parser 正确解析它并将数据输入到预期的对象中。

然后我尝试用 Django 做一些测试用例,并尝试测试文件上传。由于再次将标头附加到文件,导致解析器再次出现语法错误。

class UploadTest(APITestCase):
    def test_file_upload(self):
        c = Client()
        with open("/Users/Ren/Desktop/Capstone/Backend/projectB/VMA/testing/Test.xml") as fp:
            c.post('/upload/TestXML.xml', {'filename' : 'Test.xml', 'attachment': fp})

我的问题是:是什么导致该标题弹出/添加到上传的文件中。我猜这与我如何通过 Postman 和与 HTTPie 不同的 Django TestCase 发送 post 请求有关

view.py

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


    def post(self, request, filename, format=None):
        print(request.FILES)
        file_obj = request.FILES['file']
        fileHandler(file_obj)
        return Response(status=204)

FileReader.py

def fileHandler(file):
    filepath = file.temporary_file_path()
    print(file.read())

    tree = ET.parse(filepath)
    root = tree.getroot()

调用file.read()时的XML文件和输出

XML I need to read in (Expected Output):
<site host="192.168.212.4" name="http://192.168.212.4" port="80" ssl="false"><alerts><alertitem>\n  <pluginid>10021</pluginid>\n  <alert>X-Content-Type-Options header missing</alert>\n  <riskcode>1</riskcode>\n  <reliability>2</reliability>\n  <riskdesc>Low (Warning)</riskdesc>\n  <desc>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to \'nosniff\'.\n\tThis allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type.\n\tCurrent (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.\n\t</desc>\n  <uri>http://192.168.212.4/</uri>\n  <param/>\n  <attack/>\n  <otherinfo/>\n  <solution>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to \'nosniff\' for all web pages.\n\tIf possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.\n\t</solution>\n  <reference>\n\t</reference>\n</alertitem>


The Output when running request.FILES['file'].read() --- Current Output
b'----------------------------507481440966899800347275\r\nContent-Disposition: form-data; name=""; filename="sampleXML.xml"\r\nContent-Type: application/xml\r\n\r\n<site host="192.168.212.4" name="http://192.168.212.4" port="80" ssl="false"><alerts><alertitem>\n  <pluginid>10021</pluginid>\n  <alert>X-Content-Type-Options header missing</alert>\n  <riskcode>1</riskcode>\n  <reliability>2</reliability>\n  <riskdesc>Low (Warning)</riskdesc>\n  <desc>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to \'nosniff\'.\n\tThis allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type.\n\tCurrent (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.\n\t</desc>\n  <uri>http://192.168.212.4/</uri>\n  <param/>\n  <attack/>\n  <otherinfo/>\n  <solution>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to \'nosniff\' for all web pages.\n\tIf possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.\n\t</solution>\n  <reference>\n\t</reference>\n</alertitem>\n\n  \r\n----------------------------507481440966899800347275--\r\n'

包含不必要的:b'----------------507481440966899800347275\r\nContent-Disposition: form-data;名称=""; filename="sampleXML.xml"\r\nContent-Type: application/xml\r\n\r\n

【问题讨论】:

  • 该代码是如何发送到 API 的?显示您的前端代码。
  • 您是如何发布文件的?这是将文件附加到 POST 请求正文的标准方法,但如果您的 POST HTTP 标头包含正确的内容类型,Django 应该删除这部分。
  • 这是“Content-Type”标头的样子:“multipart/form-data;boundary=------------------ ---------507481440966899800347275" 以便 Django 可以了解文件的开始位置。
  • 我通过邮递员发送 HTTP POST 请求,我仍然不熟悉邮递员,所以这可能是问题所在。使用 Postman,我正在发送附有 XML 文件的表单数据,仅此而已。临时标头发送的内容类型是“multipart/form-data'boundary=------------------------”这是问题的原因吗?因为它是一个临时标题?
  • 我尝试使用 HTTPie 发送文件。它按预期完美运行。所以现在我倾向于邮递员成为问题 - 它出于某种原因将标题详细信息写入文件,这导致 XML Reader 出现问题

标签: python django django-rest-framework


【解决方案1】:

我玩了一会儿代码,并对 testCase 做了一点改动:

class UploadTest(APITestCase):
    def test_file_upload(self):
        c = Client()
        with open("/Users/Ren/Desktop/Capstone/Backend/projectB/VMA/testing/Test.xml") as fp:
            c.post('/upload/TestXML.xml', {'filename' : 'Test.xml', 'attachment': fp})

我改变了 {'filename' : 'Test.xml', 'attachment': fp}{'filename' : b'Test.xml', 'attachment': fp}

我记得在某处读过它,不幸的是我不记得在哪里但是...将文件转换为“字节”修复它...

【讨论】:

    猜你喜欢
    • 2021-08-21
    • 2017-12-07
    • 2011-07-03
    • 2021-01-24
    • 2021-02-08
    • 1970-01-01
    • 2012-05-19
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多