繁体   English   中英

aiohttp request.multipart()无法从浏览器上传文件中获得任何好处

[英]aiohttp request.multipart() get nothing from browser uploading files

浏览器使用vue element-ui el-upload组件上传文件,并且aiohttp作为后端接收表单数据然后保存。aiohttp request.multipart()始终为空,但request.post()可以。

提示:

   <el-upload class="image-uploader" 
        :data="dataObj" 
         drag 
         name="aaa"
        :multiple="false" 
        :show-file-list="false"
        :action="action"  -> upload url,passed from outer component
        :on-success="handleImageScucess">
      <i class="el-icon-upload"></i>
    </el-upload>

export default {
  name: 'singleImageUpload3',
  props: {
    value: String,
    action: String
  },
  methods: {
   handleImageScucess(file) {
      this.emitInput(file.files.file)
    },

  }

aiohttp:不起作用

 async def post_image(self, request):

        reader = await request.multipart()

        image = await reader.next()
        print (image.text())
        filename = image.filename
        print (filename)
        size = 0
        with open(os.path.join('', 'aaa.jpg'), 'wb') as f:
            while True:
                chunk = await image.read_chunk()

                print ("chunk", chunk)
                if not chunk:
                    break
                size += len(chunk)
                f.write(chunk)
        return await self.reply_ok([])

aiohttp:工作

async def post_image(self, request):
        data = await request.post()
        print (data)
        mp3 = data['aaa']

        filename = mp3.filename

        mp3_file = data['aaa'].file

        content = mp3_file.read()
        with open('aaa.jpg', 'wb') as f:
            f.write(content)
        return await self.reply_ok([])

浏览器控制台:

在此处输入图片说明

错误或我错过的任何东西? 请提前帮助我解决。

我认为您可能已经在aiohttp文档中查看了有关文件上传服务器的示例。 但是,该代码段含糊不清,并且该文档无法很好地说明自身。

在研究了一段时间之后,我发现request.multipart()实际上产生了一个MultipartReader实例,该实例每次调用.next()都会处理一个字段的multipart/form-data请求,从而产生另一个BodyPartReader实例。

在您无法正常工作的代码中, image = await reader.next()该行实际上从表单数据中读取了整个字段,您无法确定它实际上是哪个字段。 它可能是token字段, key字段, filename段, aaa字段...或其中的任何一个。 因此,在您无法正常工作的示例中,该post_image协程函数将仅处理请求数据中的单个字段,并且您不能十分确定它是否为aaa文件字段。

这是我的代码段,

async def post_image(self, request):
    # Iterate through each field of MultipartReader
    async for field in (await request.multipart()):
        if field.name == 'token':
            # Do something about token
            token = (await field.read()).decode()
            pass

        if field.name == 'key':
            # Do something about key
            pass

        if field.name == 'filename':
            # Do something about filename
            pass

        if field.name == 'aaa':
            # Process any files you uploaded
            filename = field.filename
            # In your example, filename should be "2C80...jpg"

            # Deal with actual file data
            size = 0
            with open(os.path.join('', filename), 'wb') as fd:
                while True:
                    chunk = await field.read_chunk()
                    if not chunk:
                        break
                    size += len(chunk)
                    fd.write(chunk)

    # Reply ok, all fields processed successfully
    return await self.reply_ok([])

上面的代码段也可以在单个请求中处理多个文件,这些文件具有重复的字段名,在您的示例中为“ aaa”。 Content-Disposition标头中的filename应由浏览器本身自动填写,因此无需担心filename

顺便说一句,当处理请求中的文件上载时, data = await request.post()将占用大量内存来加载文件数据。 所以request.post()应该包括文件上传,使用时要避免request.multipart()来代替。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM