python - aiohttp request.multipart() 从浏览器上传文件中得不到任何结果

标签 python vue.js multipartform-data aiohttp

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

View :

   <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([])

浏览器控制台:

enter image description here

错误或我遗漏的任何内容?请帮助我解决它,在此先感谢。

最佳答案

我想您可能已经在 aiohttp document about file upload server 上查看了示例.但是那个片段是模棱两可的,文档本身也没有很好地解释。

在深入研究其源代码一段时间后,我发现 request.multipart() 实际上产生了一个 MultipartReader 实例,它处理 multipart/form- data 每次调用 .next() 时请求一个字段,产生另一个 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 header中的filename应该是浏览器自己自动填充的,所以不用担心filename

顺便说一句,当处理请求中的文件上传时,data = await request.post() 会占用大量内存来加载文件数据。所以在涉及文件上传时应避免request.post(),改用request.multipart()

关于python - aiohttp request.multipart() 从浏览器上传文件中得不到任何结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50529762/

相关文章:

javascript - Axios Get 请求返回 [Proxy 代理] - Flask & Vue.js

javascript - 如何将焦点放在 vue.js 中的图像组件等按钮上

python - 比较列表以查找 python 中的公共(public)元素

python - urllib2 getparam charset 对某些站点返回 None

python - 如何在 Python 中加载 .mat 文件并单独访问列?

javascript - Vue.js:搜索栏组件 - 如果输入值长度 > 1,如何使重置按钮出现?

ajax - 似乎无法从node-formidable获取进度事件以通过socket.io发送到正确的客户端

ios - 使用请求正文批量上传图片

spring-webflux - Spring WebFlux - 通过 webClient 转发 FilePart

python - 通过 matplotlib 在 Pycharm 调试控制台中进行交互式绘图