Python,App Engine:HTTP多部分POST到Vk.Ads API

编程入门 行业动态 更新时间:2024-10-28 06:36:35
本文介绍了Python,App Engine:HTTP多部分POST到Vk.Ads API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我花了几天的时间尝试搜索示例和文档,也在ruSO上没有解决.因此,我希望可以在enSO上找到解决方案.

I tried to sole this problem myself for a few days searching on examples and documentations, also it wasn't solved on ruSO. So, I hope that solution will be found here, on enSO.

我开发了一项服务,可使用Python和Google App Engine在Vk社交网络上自动创建广告.最初,用于广告的图片会加载到我的服务器上(第1部分),然后有时将它们上传到Vk服务器上(第2.1部分和第2.2 部分).似乎图片已正确加载并存储在我的服务器上(我下载了图片并与原始图片进行了比较-每个字节都是相同的).但是我附上第1部分代码,以防万一.

I develop a service for automatic creation of ads at Vk social network using Python and Google App Engine. Initially, pictures for ads are loaded to my server (part 1), then they are uploaded to Vk server at some time (parts 2.1 and 2.2). It seems that pictures are loaded and stored on my server correctly (I downloaded them and compared with original ones — every byte is the same). But I attach the part 1 code just in case.

首先要将图片上传到Vk.Ads,我需要才能获取URL -这很简单,因此请跳过它.其次,我需要向带有字段file的链接发送POST请求,其中包含照片的二进制内容( API文档).我为此创建了两种方法( 2.1和2.2 ),但是它们都返回errcode: 2,这意味着corrupted file.在我看来,问题与请求有关,但我不排除文件在服务器上上载/存储或API的某些奇怪工作的可能性.我将不胜感激任何答复和评论.

To upload a picture to Vk.Ads firstly I need to get a URL — this is simple, so skip it. Secondly, I need to send a POST request to this link with field file with binary content of the photo (API documentation). I created two ways for that (2.1 and 2.2), but both of them returns errcode: 2 which means corrupted file. To my mind, the problem is about the requests, but I don't exclude the possibility of it files uploading/storage on my server, or some strange work of the API. I'll appreciate any answers and comments.

import webapp2 from google.appengine.ext import ndb # stores pictures on the server class Photo(ndb.Model): name = ndb.StringProperty() img = ndb.BlobProperty() @staticmethod def get(name): retval = Photo.query(Photo.name == name).get() return retval @staticmethod def create(name, blob): retval = Photo() retval.name = name retval.img = blob return retval class PhotosPage(webapp2.RequestHandler): def get(self): # general content of the page: html = '''<form action="/photos" method="post" enctype="multipart/form-data"> <input type="file" name="flimg"/> <input value="new_pic" name="flname"/> <input type="submit" value="Upload"/> </form>''' def post(self): n = str(self.request.get('flname')) f = self.request.get('flimg') p = Photo.get(n) if p: p.img = f else: p = Photo.create(n, f) p.put()

2.1.使用 urlfetch POST到API,方法#1 и海报:

2.1. POST to API, approach #1, using urlfetch и poster:

from poster.encode import multipart_encode, MultipartParam from google.appengine.api import urlfetch name = 'file' content = ... # file binary content where = ... # gotten URL options = { 'file': MultipartParam( name=name, value=content, filename=name, filetype='image/png', filesize=len(content)) } data, headers = multipart_encode(options) pocket = "".join(data) result = urlfetch.fetch( url=where, payload=pocket, method=urlfetch.POST, headers=headers)

2.2.使用requests: POST到API,方法2

2.2. POST to API, approach #2, using requests:

import requests name = 'file' content = ... # file binary content where = ... # gotten URL # I also tried without this dict; is it necessary? data = { 'fileName': name, 'fileSize': len(content), 'description': 'undefined', } result = requests.post(where, files={name: StringIO(content)}, data=data)

此外,对于第二种方法,我提取了请求的内容:

In addition, for the second approach I extracted the content of my request:

POST pu.vk/c.../upload.php?act=ads_add&mid=...&size=m&rdsn=1&hash_time=...&hash=...&rhash=...&api=1 Content-Length: 15946 Content-Type: multipart/form-data; boundary=b4b260eace4e4a7082a99753b74cf51f --b4b260eace4e4a7082a99753b74cf51f Content-Disposition: form-data; name="description" undefined --b4b260eace4e4a7082a99753b74cf51f Content-Disposition: form-data; name="fileSize" 15518 --b4b260eace4e4a7082a99753b74cf51f Content-Disposition: form-data; name="fileName" file --b4b260eace4e4a7082a99753b74cf51f Content-Disposition: form-data; name="file"; filename="file" < File binary content > --b4b260eace4e4a7082a99753b74cf51f--

更新.

由于 SwiftStudier ,我发现了问题的根源:StringIO和BytesIO与文件open的行为不同.如果仅使用open,则代码可以很好地工作,但不适用于虚拟文件.如何解决?

UPDATE.

Thanks to SwiftStudier, I found the origin of the problem: StringIO and BytesIO don't behave identical to file open. If I use just open the code works well, but it doesn't with virtual file. How it can be solved?

import requests from io import BytesIO with open('path.to/file.png', 'rb') as fin: content = BytesIO(fin.read()) token = '...' url = 'api.vk/method/ads.getUploadURL?access_token=' + token + '&ad_format=2' upload_url = requests.get(url).json()['response'] post_fields = { 'access_token': token } data_fields = { # This works: # 'file': open('path.to/file.png', 'rb') # But this does not: 'file': content } response = requests.post(upload_url, data=post_fields, files=data_fields) print(response.text)

推荐答案

经过大量实验并研究了不同的HTTP请求内容,我发现了错误代码与有效代码之间的唯一区别.它只有大约4个字节:文件名必须包含扩展名. Vk API甚至会忽略Content-Type: image/png,但需要.png或类似的文件名.因此,这不起作用:

After a lot of experiments and investigating of different HTTP requests content I found out the only difference between wrong and working code. It was about 4 bytes only: file name MUST contain the extension. Vk API even ignores Content-Type: image/png, but needs .png or similar in filename. So, this doesn't work:

requests.post(upload_url, files={ 'file': BytesIO('<binary file content>') })

但是此选项可以正常工作:

But this option works properly:

requests.post(upload_url, files={ 'file': ('file.png', BytesIO('<binary file content>'), 'image/png') })

就像这样,它不适用于GAE:

Just like this one, which is not available for GAE:

requests.post(upload_url, files={ 'file': open('/path/to/image.png', 'rb') })

StringIO和StringIO都适合该任务.如前所述,Content-Type没关系,可以只是multipart/form-data.

Both StringIO and StringIO are appropriate for that task. As mentioned, Content-Type does not matter, it can be just multipart/form-data.

更多推荐

Python,App Engine:HTTP多部分POST到Vk.Ads API

本文发布于:2023-10-12 00:28:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1483268.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Engine   HTTP   Python   App   Ads

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!