我一直在尝试使用带有请求的方框v2 api上传文件。
到目前为止我运气不好。也许这里有人可以帮我看看我实际上做错了什么。
file_name = "%s%s" % (slugify(sync_file.description), file_suffix)
file_handle = open(settings.MEDIA_ROOT + str(sync_file.document), 'rb')
folder_id = str(sync_file.patient.box_patient_folder_id)
r = requests.post(
files_url,
headers=headers,
files={
file_name: file_handle,
"folder_id": folder_id,
},
)
我的身份验证有效,因为我正在使用相同的数据创建一个文件夹。
回复看起来像这样:
{
u'status': 404,
u'code': u'not_found',
u'help_url': u'http://developers.box.com/docs/#errors',
u'request_id': u'77019510950608f791a0c1',
u'message': u'Not Found',
u'type': u'error'
}
也许这里的某个人遇到了类似的问题。
答案 0 :(得分:7)
您需要传递2个Python词典,文件和数据。文件为{uniqFileName:openFileObj}
,数据为{uniqFileName:filename}
。以下是我的盒子类的上传方法。请记住在数据中添加最终条目'folder_id': destination_id
。
def uploadFiles(self, ufiles, folid):
'''uploads 1 or more files in the ufiles list of tuples containing
(src fullpath, dest name). folid is the id of the folder to
upload to.'''
furl = URL2 + 'files/data'
data, files = {}, {}
for i, v in enumerate(ufiles):
ff = v[0]
fn = v[1]
#copy to new, renamed file in tmp folder if necessary
#can't find a way to do this with the api
if os.path.basename(ff) != fn:
dest = os.path.join(TMP, fn)
shutil.copy2(ff, dest)
ff = dest
f = open(ff, 'rb')
k = 'filename' + str(i)
data[k] = fn
files[k] = f
data['folder_id'] = folid
res = self.session.post(furl, files=files, data=data)
for k in files:
files[k].close()
return res.status_code
以下是一个示例电话:
destFol = '406600304'
ret = box.uploadFile((('c:/1temp/hc.zip', 'hz.zip'),), destFol)
就像我说的,上面的函数是一个类的方法,其中一个实例attr包含一个请求会话。但是您可以使用requests.post
代替self.session.post
,它的工作方式也相同。如果你在会话之外这样做,请记住用你的apikey和令牌添加标题。
根据文档,您应该能够通过在数据字典中为其指定新名称来重命名该文件。但我无法完成这项工作,除非将src文件复制到具有所需名称的临时目录并上传。这有点像黑客,但它确实有效。
祝你好运, 麦克答案 1 :(得分:1)
当有人要求我实施时,我想我会把它放在这里给任何试图达到类似效果的人。
files_url = "%s/files/content" % (settings.BOX_API_HOST)
headers = {"Authorization": "BoxAuth api_key=%s&auth_token=%s" %
(settings.BOX_API_KEY, self.doctor.box_auth_token)
}
file_root, file_suffix = os.path.splitext(str(self.document))
filename = "%s%s" % (slugify(self.description), file_suffix)
files = {
'filename1': open(settings.MEDIA_ROOT + str(self.document), 'rb'),
}
data = {
'filename1': filename,
'folder_id': str(self.patient.get_box_folder()),
}
r = requests.post(files_url,
headers=headers,
files=files,
data=data)
file_response = simplejson.loads(r.text)
try:
if int(file_response['entries'][0]['id']) > 0:
box_file_id = int(file_response['entries'][0]['id'])
#Update the name of file
file_update_url = "%s/files/%s" % (settings.BOX_API_HOST, box_file_id)
data_update = {"name": filename}
file_update = requests.put(file_update_url,
data=simplejson.dumps(data_update),
headers=headers)
LocalDocument.objects.filter(id=self.id).update(box_file_id=box_file_id)
except:
pass
所以从本质上讲,我需要发送文件并检索新更新文件的ID,然后向框发送另一个请求。就个人而言,我也不喜欢它,但它对我有用,并且无法找到任何其他实现正确命名的实现。
希望有人可以从这个片段中受益。
答案 2 :(得分:0)
我的解决方案,使用请求:
def upload_to_box(folder_id, auth_token, file_out):
headers = { 'Authorization' : BOX_AUTH.format(auth_token) }
url = 'https://api.box.com/2.0/files/content'
files = { 'filename': (new_file_name, open(file_out,'rb')) }
data = { 'folder_id': folder_id }
response = requests.post(url, params=data, files=files, headers=headers)
如果您可以指定new_copy
参数,但没有任何记录,并且它似乎不起作用,那将会很好。