Im trying to upload an image to the blobstore and return the serving url, this is where im at so far:
url ='http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key=b25b959554ed76058ac220b7b2e0a026&artist=blink-182&track=dammit&format=json'
result = urlfetch.fetch(url=url, deadline=10, method=urlfetch.GET,).content
if result:
data = json.loads(result)
imageUrl = data['track']['album']['image'][3]['#text']
result = urlfetch.fetch(imageUrl)
if result.status_code == 200:
image_result = db.Blob(result.content)
I need to return the blobs serving url so I can save it with another entity.
any help is appreciated
thanks
J
You've confused two things.
A db.Blob is the type of a blob stored within a model. It doesn't have a "serving URL". If you want to serve one, you need to write view code to load the model instance it's stored in from the datastore, and return the blob data directly.
If you want to store blobs and serve them independently of datastore models, you need to use the (experimental) blobstore API.
The documentation has a good writeup on how to write files to the blobstore programatically. You can then pass that to the images API to get a URL:
from google.appengine.api import images
url = images.get_serving_url(blob_key)
Related
This method of getting Google Drive file thumbnails has been working for me but seems to have stopped recently.
All answers I can find online indicate that this is because thumbnailLink requires authorization (eg). However, I'm am accessing the thumbnails with authorized access tokens. I can get the file info using the Drive API "Files: get" with these access tokens but the thumbnailLink returns 404.
print(http)
# <google_auth_httplib2.AuthorizedHttp object at 0x11561d0f0>
# An instance of google_auth_httplib2.AuthorizedHttp
url = 'https://www.googleapis.com/drive/v3/files/%s?fields=thumbnailLink' % file_id
response, content = http.request(url)
data = json.loads(content)
print(data['thumbnailLink'])
# https://docs.google.com/u//feeds/vt?gd=true&id=***fileID***&v=203&s=***&sz=s220
# Works ✓
response, content = http.request(data['thumbnailLink'])
print(response['status'])
# 404
# :(
Also giving a 404 error:
thumbnailLink + "&access_token=" + YOURTOKEN; as suggested here.
Opening thumbnailLink in a browser (logged in to Google as the file owner).
Opening a modified thumbnailLink in a browser - replacing /u// with /u/0/, /u/1/ , /u/2/ (When I open drive as this user the URL is https://drive.google.com/drive/u/1/my-drive)
Does anyone know a reliable way to get Google Drive thumbnail image files?
I believe your goal as follows.
You want to retrieve the thumbnail from the thumbnail link retrieved by the method of "files.get" in Drive API.
From your sample thumbnail link, you want to retrieve the thumbnail from Google Docs (Document, Spreadsheet, and so on).
Issue and workaround:
In the current stage, it seems that the situation of 404 from the thumbnail is the bug. This has already been reported to the Google issue tracker. Ref And it seems that Google side has already been known. Unfortunately, I think that this is the current direct answer. And also, I believe that this issue will be resolved by the future update.
Here, as the current workaround, how about converting it to PDF file and retrieve the thumbnail? In this case, the thumbnail link can be used. The flow of this workaround is as follows.
Convert Google Docs to a PDF file.
The PDF file is created to the same folder of the Google Docs.
Retrieve the thumbnail link from the created PDF file.
When above flow is converted to the python script, it becomes as follows.
Sample script:
Before you use this script, please set the access token and file ID. In this case, in order to request multipart/form-data with the simple script, I used requests library.
import json
import httplib2
import requests
import time
http = httplib2.Http()
access_token = '###' # Please set the access token.
file_id = '###' # Please set the file ID.
headers = {"Authorization": "Bearer " + access_token}
# 1. Retrieve filename and parent ID.
url1 = "https://www.googleapis.com/drive/v3/files/" + file_id + "?fields=*"
res, res1 = http.request(url1, 'GET', headers=headers)
d = json.loads(res1.decode('utf-8'))
# 2. Retrieve PDF data by converting from the Google Docs.
url2 = "https://www.googleapis.com/drive/v3/files/" + file_id + "/export?mimeType=application%2Fpdf"
res, res2 = http.request(url2, 'GET', headers=headers)
# 3. Upload PDF data as a file to the same folder of Google Docs.
para = {'name': d['name'] + '.pdf', 'parents': d['parents']}
files = {
'data': ('metadata', json.dumps(para), 'application/json; charset=UTF-8'),
'file': res2
}
res3 = requests.post(
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
headers=headers,
files=files
)
obj = res3.json()
# It seems that this is required to use by creating the thumbnail link from the uploaded file.
time.sleep(5)
# 4. Retrieve thumbnail link of the uploaded PDF file.
url3 = "https://www.googleapis.com/drive/v3/files/" + obj['id'] + "?fields=thumbnailLink"
res, res4 = http.request(url3, 'GET', headers=headers)
data = json.loads(res4.decode('utf-8')) # or data = json.loads(res4)
print(data['thumbnailLink'])
# 5. Retrieve thumbnail.
response, content = http.request(data['thumbnailLink'])
print(response['status'])
print(content)
When you run this script, the Google Docs file is exported as the PDF data, and the PDF data is uploaded to Google Drive and retrieve the thumbnail link.
Note:
In this case, please include the scope of https://www.googleapis.com/auth/drive to the scopes of your access token. Because the file is uploaded.
In order to retrieve the file metadata and export the PDF file and upload the data, the access token is required to be used. But when the thumbnail is retrieved from the thumbnail link, the access token is not required to be used.
After January, 2020, the access token cannot be used with the query parameter of access_token=###.So please use the access token to the request header. Ref
When above issue was resolved, I think that you can use your script.
References:
Files: get
Files: export
Files: create
Scenario: an image file stored in a GCP bucket need to be sent to a third-party REST endpoint via a POST
Question: Is this really the best pattern? Is there a more efficient less verbose way?
We have images being uploaded by a mobile app to a GCP Storage bucket. When the finalize event for the image upload fires we have a GCP Cloud Function (Python 3) that reacts to this by getting ref to uploaded image, downloads it to a temp file, and then uses that temp file as the image source for the POST. This is our current code and it works, but to my eye seems convoluted with the multiple open commands. More specifically: is there a better way to simply get the image blob from GCP Storage and simply attach it to the POST call without first saving it as a local file and then opening it so it can be attached to the POST?
def third_party_upload(data, context):
# get image from bucket
storage_client = storage.Client()
bucket = storage_client.bucket(data['bucket'])
image_blob = bucket.get_blob(data['name'])
download_path = '/tmp/{}.jpg'.format(str(uuid.uuid4())) #temp image file download location
# save GCP Storage blob as a temp file
with open(download_path, 'wb') as file_obj:
image_blob.download_to_file(file_obj)
# open temp file and send to 3rd-party via rest post call
with open(download_path, 'rb') as img:
files = {'image': (data['name'], img, 'multipart/form-data', {'Expires': '0'}) }
headers = {
'X-Auth-Token': api_key,
'Content-Type': 'image/jpg',
'Accept': 'application/json'
}
# make POST call
response = requests.post(third_party_endpoint, headers=headers, files=files)
print('POST response:', response)
Update: a couple of commenters have mentioned that Signed URLs are a possibility and I agree they are an excellent choice. However we are stuck with a requirement to include the image binary as the POST body. Signed-URLs won't work in this case.
The HTTP method POST requires data. You must provide that data in the HTTP request. There is no magic method to obtain Cloud Storage data except to read it. The process is to read the data from Cloud Storage and then provide that data to the POST request.
If you're able to send a URL to the third-party endpoint instead of the actual image contents, you could use Signed URLs give time-limited access to the image without needing to provide the 3rd party access to the bucket or make the bucket public.
More information here: https://cloud.google.com/storage/docs/access-control/signed-urls
I am trying to upload image/file to clodinary to get back the url using this code
medical_file = request.FILES['medical_file']
out = cloudinary.uploader.upload(File.open(medical_file, "rb"))
url = out['url']
medical_file_url = url
And I am successfully getting the url as well(I have printed that on my console)
But then I am getting this error of : cloudinary.api.Error: Empty file
Per Cloudinary's documentation:
In cases where images are uploaded by users of your Django application through a web form, you can pass the parameter of your Django's request.FILES to the upload method
So in your case, you can upload the file on the server-side by passing request.FILES['medical_file'] directly to the upload method:
out = cloudinary.uploader.upload(request.FILES['medical_file'])
Sorry Guys, I am new to Django, I am stuck with images upload.
I have a REST_API for image upload. I pass the image and inside API get that image by using
request.FILES['fileToUpload'].
Now I have an external API, which uploads an image on my behalf, that API is working fine on the postman.
Here is the path of that API.
http://164.68.110.65/file_load.php
But in Django. I am not able to pass the image to this API. I have tried many ways.
like these.
image = request.FILES['fileToUpload']
temp = Image.open(image)
byte_io = BytesIO()
temp.save(byte_io, 'png')
files = {'fileToUpload': byte_io.getvalue() }
response = requests.post( self.URL, files=files)
print(response.status_code, response.content, response.reason)
but it always giving me an error that image format is not matched.
can you please tell me, in python-requests, how we should pass images or files that are got my request.FILES['file_name_any'].
Thanks.
I will be very thankful for your favor.
Your image is an UploadedFile or a TemporaryUploadedFile which is a subclass of File. So you can just .open() it normally as any other File object:
with image.open('rb') as f:
files = {'fileToUpload': f}
response = requests.post(self.URL, files=files)
No need to take the detour through saving the file first.
I am trying to upload a file to s3 from a form via ajax. I am using fineuploader http://fineuploader.com/ on the client side and webapp2 on the server side. it sends the parameter as qqfile in the request and I can see the image data in the request headers but I have no idea how to get it back in browsers that do not use the multipart encoding.
This is how I was doing it in the standard html form post with multipart.
image = self.request.POST["image"]
this gives me the image name and the image file
currently I have only been able to get the image filename back not the data with
image = self.request.get_all('image')
[u'image_name.png']
when using the POST I get a warning about the content headers being application/octet-stream
<NoVars: Not an HTML form submission (Content-Type: application/octet-stream)>
How do I implement a BlobStoreHandler in webapp2 outside of GAE?
Your question code is not very clear to me. But you can use an example.
Have a look at this article from Nick Johnson. He implements a dropbox service using app engine blobstore and Plupload in the client : http://blog.notdot.net/2010/04/Implementing-a-dropbox-service-with-the-Blobstore-API-part-2
I ended up using fineuploader http://fineuploader.com/ which sends a multipart encoded form to my handler endpoint.
inside the handler I could simply just reference the POST and then read the FieldStorage Object into a cStringIO object.
image = self.request.POST["qqfile"]
imgObj = cStringIO.StringIO(image.file.read())
# Connect to S3...
# create s3 Key
key = bucket.new_key("%s" % uuid.uuid4());
# guess mimetype for headers
file_mime_type = mimetypes.guess_type(image.filename)
if file_mime_type[0]:
file_headers = {"Content-Type": "%s" % file_mime_type[0]}
else:
file_headers = None
key.set_contents_from_string(imgObj.getvalue(), headers=file_headers)
key_str = key.key
#return JSON response with key and append to s3 url on front end.
note: qqfile is the parameter fineuploader uses.
I am faking the progress but that is ok for my use case no need for BlobStoreUploadHandler.