How to get dynamic url of file uploaded to sharepoint using python? - python-3.x

My code does following tasks on daily basis:
Create a date folder on sharepoint.DONE
Create a category folder in the date folder of sharepoint. DONE
Upload a file in respective category folder. DONE
4. Find the url of file. PENDING
Send the url on email. DONE
def upload_files(base_url, site, access_token, fileName, filePath, fileFolderUrl):
try:
fileHandle = open(filePath, 'rb')
#fileFolderUrl = f'Shared Documents/Output/{subFolder}'
requestFileUploadUrl = f"{base_url}/{site}/_api/web/GetFolderByServerRelativeUrl('{fileFolderUrl}')/Files/add(url='{fileName}',overwrite=true)"
headers = {
'Accept':'application/json; odata=verbose',
'Content-Type':'application/json; odata=verbose',
'Authorization': 'Bearer {}'.format(access_token)
}
uploadFileResult = requests.post(requestFileUploadUrl, headers=headers, data=fileHandle)
if uploadFileResult.status_code == 200:
return "success"
else:
return "failure"
except Exception as e:
print(f"Error in uploading files to sharepoint:{e}")
return "error"
Can someone please help me understand the process to obtain the url of this file that I am required to upload in dynamically created folders on sharepoint using python3+?
So,the structure is : SharedDocuments/Output/Today's Date/CategoryA/file.xlsx

One solution could be to create the URL manually as you already know the url, the site and the name of the file.
I figure out that you can create the link to share a file with this pattern :
<base_url>/<site>/<FileFolderUrl>/<File>?&web=1
For example : https://company.sharepoint.com/sites/test/Documents%20partages/testing.jpg?&web=1
It works only for people that already have access it.
I have not yet tested in an automatic solution but only by hand in an empirical way

I know it's been a long while but was scrolling through it today and thought of answering it. Hope it can be helpful to someone in the future.
def get_out_file_url(base_url, site, access_token, file_folder, fileName):
"""
These are random examples of file_folder and base_url
file_folder = 'Shared Documents/Output/Dated/Category'
base_url = 'https://company.sharepoint.com'
"""
requestFileGetUrl = f'{base_url}/sites/{site}/_api/web/GetFolderByServerRelativeUrl(\'' + fileUrl + '/'+ '\')/files?$filter'
headers = {
'Accept':'application/json; odata=verbose',
'Content-Type':'application/json; odata=verbose',
'Authorization': 'Bearer {}'.format(access_token)
}
getFileResult = requests.get(requestFileGetUrl, headers=headers)
values = getFileResult.json()
fileData = values['d']['results']
for key in fileData:
if key['Name'] == fileName:
fileURLLink = key['ServerRelativeUrl']
fileCreatedTime = key['TimeCreated']
fileLastModified = key['TimeLastModified']
fileNewUrl = base_url + urllib.parse.quote(fileURLLink)
return fileNewUrl
else:
return file_folder

Related

upload image from url to wordpress using rest api and python

I'm trying to upload image from url to wordpress without saving it in my device using python and rest api , i'm really close to achive that i just can't find where i'm lost
i keep getting 500 and this error :
{"code":"rest_upload_unknown_error","message":"Sorry, you are not allowed to upload this file type.","data":{"status":500}}
my code :
import base64, requests
def header(user, password):
credentials = user + ':' + password
token = base64.b64encode(credentials.encode())
header_json = {'Authorization': 'Basic ' + token.decode('utf-8'),
'Content-Disposition' : 'attachment; filename=%s'% "test1.jpg"}
return header_json
def upload_image_to_wordpress(file_path, header_json):
media = {'file': file_path,'caption': 'My great demo picture'}
responce = requests.post("https://website.com/wp-json/wp/v2/media", headers = header_json, files = media)
print(responce.text)
heder = header("user","password") #username, application password
url = "https://cdn.pixabay.com/photo/2021/11/30/08/24/strawberries-6834750_1280.jpg"
raw = requests.get(url).content
upload_image_to_wordpress(raw,heder)
after trying many solutions i found out working one
from tempfile import NamedTemporaryFile
url = "https://cdn.pixabay.com/photo/2021/11/30/08/24/strawberries-6834750_1280.jpg"
raw = requests.get(url).content
with NamedTemporaryFile(delete=False,mode="wb",suffix=".jpg") as img :
img.write(raw)
# print(f.file())
c = open(img.name,"rb")
upload_image_to_wordpress(c,heder)

How to create Wiki Subpages in Azure Devops thru Python?

My Azure devops page will look like :
I have 4 pandas dataframes.
I need to create 4 sub pages in Azure devops wiki from each dataframe.
Say, Sub1 from first dataframe, Sub2 from second dataframe and so on.
My result should be in tab. The result should look like :
Is it possible to create subpages thru API?
I have referenced the following docs. But I am unable to make any sense. Any inputs will be helpful. Thanks.
https://github.com/microsoft/azure-devops-python-samples/blob/main/API%20Samples.ipynb
https://learn.microsoft.com/en-us/rest/api/azure/devops/wiki/pages/create%20or%20update?view=azure-devops-rest-6.0
To create a wiki subpage, you should use Pages - Create Or Update api, and specify the path to pagename/subpagename. Regarding how to use the api in Python, you could use Azure DevOps Python API and refer to the sample below:
def create_or_update_page(self, parameters, project, wiki_identifier, path, version, comment=None, version_descriptor=None):
"""CreateOrUpdatePage.
[Preview API] Creates or edits a wiki page.
:param :class:`<WikiPageCreateOrUpdateParameters> <azure.devops.v6_0.wiki.models.WikiPageCreateOrUpdateParameters>` parameters: Wiki create or update operation parameters.
:param str project: Project ID or project name
:param str wiki_identifier: Wiki ID or wiki name.
:param str path: Wiki page path.
:param String version: Version of the page on which the change is to be made. Mandatory for `Edit` scenario. To be populated in the If-Match header of the request.
:param str comment: Comment to be associated with the page operation.
:param :class:`<GitVersionDescriptor> <azure.devops.v6_0.wiki.models.GitVersionDescriptor>` version_descriptor: GitVersionDescriptor for the page. (Optional in case of ProjectWiki).
:rtype: :class:`<WikiPageResponse> <azure.devops.v6_0.wiki.models.WikiPageResponse>`
"""
route_values = {}
if project is not None:
route_values['project'] = self._serialize.url('project', project, 'str')
if wiki_identifier is not None:
route_values['wikiIdentifier'] = self._serialize.url('wiki_identifier', wiki_identifier, 'str')
query_parameters = {}
if path is not None:
query_parameters['path'] = self._serialize.query('path', path, 'str')
if comment is not None:
query_parameters['comment'] = self._serialize.query('comment', comment, 'str')
if version_descriptor is not None:
if version_descriptor.version_type is not None:
query_parameters['versionDescriptor.versionType'] = version_descriptor.version_type
if version_descriptor.version is not None:
query_parameters['versionDescriptor.version'] = version_descriptor.version
if version_descriptor.version_options is not None:
query_parameters['versionDescriptor.versionOptions'] = version_descriptor.version_options
additional_headers = {}
if version is not None:
additional_headers['If-Match'] = version
content = self._serialize.body(parameters, 'WikiPageCreateOrUpdateParameters')
response = self._send(http_method='PUT',
location_id='25d3fbc7-fe3d-46cb-b5a5-0b6f79caf27b',
version='6.0-preview.1',
route_values=route_values,
query_parameters=query_parameters,
additional_headers=additional_headers,
content=content)
response_object = models.WikiPageResponse()
response_object.page = self._deserialize('WikiPage', response)
response_object.eTag = response.headers.get('ETag')
return response_object
More details, you could refer to the link below:
https://github.com/microsoft/azure-devops-python-api/blob/451cade4c475482792cbe9e522c1fee32393139e/azure-devops/azure/devops/v6_0/wiki/wiki_client.py#L107
Able to achieve with rest api
import requests
import base64
import pandas as pd
pat = 'TO BE FILLED BY YOU' #CONFIDENTIAL
authorization = str(base64.b64encode(bytes(':'+pat, 'ascii')), 'ascii')
headers = {
'Accept': 'application/json',
'Authorization': 'Basic '+authorization
}
df = pd.read_csv('sf_metadata.csv') #METADATA OF 3 TABLES
df.set_index('TABLE_NAME', inplace=True,drop=True)
df_test1 = df.loc['CURRENCY']
x1 = df_test1.to_html() # CONVERTING TO HTML TO PRESERVE THE TABULAR STRUCTURE
#JSON FOR PUT REQUEST
SamplePage1 = {
"content": x1
}
#API CALLS TO AZURE DEVOPS WIKI
response = requests.put(
url="https://dev.azure.com/xxx/yyy/_apis/wiki/wikis/yyy.wiki/pages?path=SamplePag2&api-version=6.0", headers=headers,json=SamplePage1)
print(response.text)
Based on #usr_lal123's answer, here is a function that can update a wiki page or create it if it doesn't:
import requests
import base64
pat = '' # Personal Access Token to be created by you
authorization = str(base64.b64encode(bytes(':'+pat, 'ascii')), 'ascii')
def update_or_create_wiki_page(organization, project, wikiIdentifier, path):
# Check if page exists by performing a Get
headers = {
'Accept': 'application/json',
'Authorization': 'Basic '+authorization
}
response = requests.get(url=f"https://dev.azure.com/{organization}/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path={path}&api-version=6.0", headers=headers)
# Existing page will return an ETag in their response, which is required when updating a page
version = ''
if response.ok:
version = response.headers['ETag']
# Modify the headers
headers['If-Match'] = version
pageContent = {
"content": "[[_TOC_]] \n ## Section 1 \n normal text"
+ "\n ## Section 2 \n [ADO link](https://azure.microsoft.com/en-us/products/devops/)"
}
response = requests.put(
url=f"https://dev.azure.com/{organization}/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path={path}&api-version=6.0", headers=headers,json=pageContent)
print("response.text: ", response.text)

Download Zoom Recordings to Local Machine and use Resumable Upload Method to upload the video to Google Drive

I have built a function in Python3 that will retrieve the data from a Google Spreadsheet. The data will contain the Recording's Download_URL and other information.
The function will download the Recording and store it in the local machine. Once the video is saved, the function will upload it to Google Drive using the Resumable Upload method.
Even though the response from the Resumable Upload method is 200 and it also gives me the Id of the file, I can't seem to find the file anywhere in my Google Drive. Below is my code.
import os
import requests
import json
import gspread
from oauth2client.service_account import ServiceAccountCredentials
DOWNLOAD_DIRECTORY = 'Parent_Folder'
def upload_recording(file_location,file_name):
filesize = os.path.getsize(file_location)
# Retrieve session for resumable upload.
headers = {"Authorization": "Bearer " + access_token, "Content-Type": "application/json"}
params = {
"name": file_name,
"mimeType": "video/mp4"
}
r = requests.post(
"https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable",
headers=headers,
data=json.dumps(params)
)
print(r)
location = r.headers['Location']
# Upload the file.
headers = {"Content-Range": "bytes 0-" + str(filesize - 1) + "/" + str(filesize)}
r = requests.put(
location,
headers=headers,
data=open(file_location, 'rb')
)
print(r.text)
return True
def download_recording(download_url, foldername, filename):
upload_success = False
dl_dir = os.sep.join([DOWNLOAD_DIRECTORY, foldername])
full_filename = os.sep.join([dl_dir, filename])
os.makedirs(dl_dir, exist_ok=True)
response = requests.get(download_url, stream=True)
try:
with open(full_filename, 'wb') as fd:
for chunk in response.iter_content(chunk_size=512 * 1024):
fd.write(chunk)
upload_success = upload_recording(full_filename,filename)
return upload_success
except Exception as e:
# if there was some exception, print the error and return False
print(e)
return upload_success
def main():
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive"]
creds = ServiceAccountCredentials.from_json_keyfile_name('creds.json', scope)
client = gspread.authorize(creds)
sheet = client.open("Zoom Recordings Data").sheet1
data = sheet.get_all_records()
# Get the Recordings information that are needed to download
for index in range(len(sheet.col_values(9))+1 ,len(data)+2):
success = False
getRow = sheet.row_values(index)
session_name = getRow[0]
topic = getRow[1]
topic = topic.replace('/', '')
topic = topic.replace(':', '')
account_name = getRow[2]
start_date = getRow[3]
file_size = getRow[4]
file_type = getRow[5]
url_token = getRow[6] + '?access_token=' + getRow[7]
file_name = start_date + ' - ' + topic + '.' + file_type.lower()
file_destination = session_name + '/' + account_name + '/' + topic
success |= download_recording(url_token, file_destination, file_name)
# Update status on Google Sheet
if success:
cell = 'I' + str(index)
sheet.update_acell(cell,'success')
if __name__ == "__main__":
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'creds.json',
scopes='https://www.googleapis.com/auth/drive'
)
delegated_credentials = credentials.create_delegated('Service_Account_client_email')
access_token = delegated_credentials.get_access_token().access_token
main()
I'm still trying to figure out how to upload the video to the folder that it needs to be. I'm very new to Python and the Drive API. I would very appreciate if you can give me some suggestions.
How about this answer?
Issue and solution:
Even though the response from the Resumable Upload method is 200 and it also gives me the Id of the file, I can't seem to find the file anywhere in my Google Drive. Below is my code.
I think that your script is correct for the resumable upload. From your above situation and from your script, I understood that your script worked, and the file has been able to be uploaded to Google Drive with the resumable upload.
And, when I saw your issue of I can't seem to find the file anywhere in my Google Drive and your script, I noticed that you are uploading the file using the access token retrieved by the service account. In this case, the uploaded file is put to the Drive of the service account. Your Google Drive is different from the Drive of the service account. By this, you cannot see the uploaded file using the browser. In this case, I would like to propose the following 2 methods.
Pattern 1:
The owner of the uploaded file is the service account. In this pattern, share the uploaded file with your Google account. The function upload_recording is modified as follows. And please set your email address of Google account to emailAddress.
Modified script:
def upload_recording(file_location, file_name):
filesize = os.path.getsize(file_location)
# Retrieve session for resumable upload.
headers1 = {"Authorization": "Bearer " + access_token, "Content-Type": "application/json"} # Modified
params = {
"name": file_name,
"mimeType": "video/mp4"
}
r = requests.post(
"https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable",
headers=headers1, # Modified
data=json.dumps(params)
)
print(r)
location = r.headers['Location']
# Upload the file.
headers2 = {"Content-Range": "bytes 0-" + str(filesize - 1) + "/" + str(filesize)} # Modified
r = requests.put(
location,
headers=headers2, # Modified
data=open(file_location, 'rb')
)
# I added below script.
fileId = r.json()['id']
permissions = {
"role": "writer",
"type": "user",
"emailAddress": "###" # <--- Please set your email address of your Google account.
}
r2 = requests.post(
"https://www.googleapis.com/drive/v3/files/" + fileId + "/permissions",
headers=headers1,
data=json.dumps(permissions)
)
print(r2.text)
return True
When you run above modified script, you can see the uploaded file at "Shared with me" of your Google Drive.
Pattern 2:
In this pattern, the file is uploaded to the shared folder using the resumable upload with the service account. So at first, please prepare a folder in your Google Drive and share the folder with the email of the service account.
Modified script:
Please modify the function upload_recording as follows. And please set the folder ID you shared with the service account.
From:
params = {
"name": file_name,
"mimeType": "video/mp4"
}
To:
params = {
"name": file_name,
"mimeType": "video/mp4",
"parents": ["###"] # <--- Please set the folder ID you shared with the service account.
}
When you run above modified script, you can see the uploaded file at the shared folder of your Google Drive.
Note:
In this case, the owner is the service account. Of course, the owner can be also changed.
Reference:
Permissions: create

Unable to download completed envelope pdf using dcousign rest API

I am trying to access signed envelop using REST API and I getting response from REST API but when I save the response to pdf, it doesn't show any content.
Below is a small python code that I wrote to achieve this.
import json
import requests
url = "https://demo.docusign.net/restapi/v2/accounts/[Account ID]/envelopes/[Envelope ID]/documents/1"
headers = {'X-DocuSign-Authentication': '<DocuSignCredentials><Username>[username]</Username><Password>[password]</Password><IntegratorKey>[Integrator Key]</IntegratorKey></DocuSignCredentials>'}
Response = requests.get(url, headers = headers)
file = open("agreement.pdf", "w")
file.write(Response.text.encode('UTF-8'))
file.close()
Try using httplib2, also the content is always going to come back formatted as a PDF through DocuSign, so I don't think you need to set the encoding.
import json
import requests
import httplib2
url = "https://demo.docusign.net/restapi/v2/accounts/[Account ID]/envelopes/[Envelope ID]/documents/1"
headers = {'X-DocuSign-Authentication': '<DocuSignCredentials><Username>[username]</Username><Password>[password]</Password><IntegratorKey>[Integrator Key]</IntegratorKey></DocuSignCredentials>'}
http = httplib2.Http();
response, content = http.request(url, 'GET', headers = headers)
status = response.get('status');
if (status != '200'):
print("Error: " % status); sys.exit();
file = open("agreement.pdf", "w")
file.write(content)
file.close()
Have you seen the DocuSign API Walkthroughs? These are accessible through the Developer Center, I suggest you take a look as there are code samples for 9 common API use-cases, each written in Python (and 5 other languages), including the 6th walkthrough which shows you how to query and download docs from completed envelopes.
The main problem with your code is that it's assuming the response only contains the document data, which is not correct. The response will have headers and a body, that's why you can't render your document when you simply write it all to a file.
I suggest you use httplib2, which is what the following Python sample uses:
http://iodocs.docusign.com/APIWalkthrough/getEnvelopeDocuments
Here is a snippet of the Python code but check out the above link for full code:
#
# STEP 2 - Get Envelope Document(s) Info and Download Documents
#
# append envelopeUri to baseURL and use in the request
url = baseUrl + envelopeUri + "/documents";
headers = {'X-DocuSign-Authentication': authenticateStr, 'Accept': 'application/json'};
http = httplib2.Http();
response, content = http.request(url, 'GET', headers=headers);
status = response.get('status');
if (status != '200'):
print("Error calling webservice, status is: %s" % status); sys.exit();
data = json.loads(content);
envelopeDocs = data.get('envelopeDocuments');
uriList = [];
for docs in envelopeDocs:
# print document info
uriList.append(docs.get("uri"));
print("Document Name = %s, Uri = %s" % (docs.get("name"), uriList[len(uriList)-1]));
# download each document
url = baseUrl + uriList[len(uriList)-1];
headers = {'X-DocuSign-Authentication': authenticateStr};
http = httplib2.Http();
response, content = http.request(url, 'GET', headers=headers);
status = response.get('status');
if (status != '200'):
print("Error calling webservice, status is: %s" % status); sys.exit();
fileName = "doc_" + str(len(uriList)) + ".pdf";
file = open(fileName, 'w');
file.write(content);
file.close();
print ("\nDone downloading document(s)!\n");

Why is my excel add-in getting corrupted?

I have a link to an excel add-in I let users download. I am using flask + mod_wsgi.
#app.route('/link/')
def download_addin():
parent_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '/static/'
response = make_response()
response.headers['Cache-Control'] = 'no-cache'
response.headers['Content-Type'] = 'application/vnd.ms-excel.addin.macroEnabled.12'
response.headers['Content-Disposition'] = 'attachment; filename=my_addin.xlam'
return response
I download the file but when I use it in Excel I get a warning "Excel cannot open the file 'my_addin.xlam' because the file format or file extension is not valid...'
Thanks!
You need to return the file as part of the response. Try something like
#app.route('/link/')
def download_addin():
parent_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '/static/'
with open(os.path.join(parent_dir, 'my_addin.xlam')) as f:
response = make_response(f.read())
response.headers['Cache-Control'] = 'no-cache'
response.headers['Content-Type'] = 'application/vnd.ms-excel.addin.macroEnabled.12'
response.headers['Content-Disposition'] = 'attachment; filename=my_addin.xlam'
return response
Without doing this you'll download an empty file. That's probably why Excel doesn't like the format.

Resources