I am building a testing website. In login confirmation, I have to show the examinee their pictures, which is already saved in Google Drive Folder.
$optParams = array(
'pageSize' => 1,
'fields' => 'nextPageToken, files(contentHints/thumbnail,fileExtension,id,name,size)',
'q' =>"mimeType contains 'image/' AND name contains '".$imageId."' AND '".$folderIdId."' in parents"
);
$results = $googleDriveService->files->listFiles($optParams);
if (count($results->getFiles()) == 0) {
print "No files found.\n";
} else {
print "Files:\n";
foreach ($results->getFiles() as $file) {
printf("%s (%s)\n", $file->getName(), $file->getId());
}
}
This is what I used to get the file ID. Now in order to preview the image to the page, do I have to download the image (then delete it later) in order to show it, or is there another way to do it without downloading?
Answer:
While Drive is not designed to be a hosting platform, you use the preview link as a workaround.
More Information:
I really should reiterate here: Drive is not designed to be an image hosting platform. It is a file sharing and cloud storage solution primarily, but does provide methods of viewing images via preview, view and embed links.
You can use the following link, replacing [ID] with your image ID to embed or preview an image in a page:
https://drive.google.com/uc?export=view&id=[ID]
NB: While this works, the image will load slowly as image hosting is not the M.O. of Drive.
There is also an iframe option provided in the form of an embed:
<iframe src="https://drive.google.com/file/d/[ID]/preview" width="640" height="480"></iframe>
This iframe embed is obtainable from the Drive UI:
After double-clicking your image at drive.google.com, and following the ⋮ > Open in new window menu item, in the newly opened tab follow the ⋮ > Embed item... menu option and the iframe code will open in a modal.
This works for me. You need to follow the GOOGLE DRIVE API docs. This code takes a file and uploads it to google drive. Records the URL and the "name" in a database for use in displaying the images later. I installed multer in express.js to help with multiple image uploads.
app.post('/api/uploadmultiple', uploader.any("files", 12),
async (req, res, next) => {
const scopes = [
'https://www.googleapis.com/auth/drive'
];
const stream = require('stream');
const { google } = require('googleapis');
const credentials = require('./google-credentials.json');
let fileObject = req.files[0];
let bufferStream = new stream.PassThrough();
bufferStream.end(fileObject.buffer);
const auth = new google.auth.JWT(
credentials.client_email, null,
credentials.private_key, scopes
);
const drive = google.drive({ version: "v3", auth });
const fileName = req.files[0].originalname;
const fileType = req.files[0].mimetype;
var fileMetadata = {
name: fileName, // file name that will be saved in google drive
};
var media = {
mimeType: fileType,
body: req.files[0].buffer, // Reading the file from our server
};
var petname = req.body.petname;
// Uploading Single image to drive
drive.files.create(
{
media: {
mimeType: fileType,
body: bufferStream
},
resource: {
name: fileName,
// if you want to store the file in the root, remove this parents
parents: ['GET THIS ID FROM GOOGLE DRIVE']
},
fields: 'id',
}).then(function (resp) {
if (resp.data) {
res.status(200).end("File uploaded");
var fileLocation = "https://drive.google.com/uc?id=" + resp.data.id;
console.log("Upload Success", fileLocation);
db.addPet(petname, fileLocation);
db.addImage(petname, fileName, fileLocation);
}
console.log(resp.data.id,'resp');
}).catch(function (error) {
console.log(error);
res.status(500);
})});
Related
i'v been looking for a solution for this issue for a week now, tried a lot of stuff nothing worked for me, I'm working on a project with react-native built on expo, what i'm trying to do is uploading an image using Imagepicker, i tried submitting it using axios and fetch, i'm able to send text data like (username, email ...) but can't send a file to the server, it doesn't recognise it a all, all it gives me is [object object], if any body was successful on doing that with php please share piece of your code, I did tried the backend with an html form and the file uploaded with no issues.
Solution
let picker = await ImagePicker.launchImageLibraryAsync({ base64: true });
const picker = selectedImage.base64;
This will return a base64 encoded image data, all you have to do is send it as a text field to the php server, decode it and put it into a file like this:
file_put_contents("example.jpg", base64_decode($_POST['image']));
And yeah, it's working
the simplest solutions is to use the base64 image format.
You can set in the options bese64 to true:
let picker = await ImagePicker.launchImageLibraryAsync({ base64:true });
And append the value in a classic json object and avoid the multipar/fomr-data, just for php decode the base64 image.
React native
// State variable to hold the picked image
const [selectedImage, setSelectedImage] = useState(false);
// Use image picker to choose a picture
let openImage = async () => {
let permission = await ImagePicker.requestCameraRollPermissionsAsync();
if (permission.granted == false) {
return;
}
let picker = await ImagePicker.launchImageLibraryAsync();
setSelectedImage(picker);
}
// Upload image to the server
const uploadimage = async () => {
const payload = new FormData();
payload.append('image', {
uri: selectedImage.uri,
type: selectedImage.type,
name: selectedImage.fileName
})
const config = {
body: payload,
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data'
}
};
let response = await fetch('http://192.168.1.6/php_upload/upload.php', config);
console.log(response);
}
// PHP Backend
$target_file = "uploads/" . basename($_FILES["image"]["name"]);
if ( move_uploaded_file($_FILES["photo"]["tmp_name"], $target_file) )
{
echo "The file ". basename( $_FILES["photo"]["name"]). " has been uploaded.";
}
else
{
echo "Sorry, there was an error uploading your file.";
}
now im doing AXIOS code combine with laravel to get image from instagram URL. the URL is this https://www.instagram.com/p/B_zZCRpB895/media/?size=t
AXIOS is new from me. to get the image, i tried this simple code. i set this code into my frontend site
<img id="imgsrc" src="" >
<script>
axios
.get('https://www.instagram.com/p/B_zZCRpB895/media/?size=t', {
responseType: 'arraybuffer'
})
.then(response => {
const buffer = Buffer.from(response.data, 'base64');
document.getElementById("imgsrc").src = Buffer;
console.log(Buffer);
})
.catch(ex => {
console.error(ex);
});
</script>
but the image not display into <img id="imgsrc" src="" >
i really want that, when we open the page. the instagram image can display.
how to solve this matter. please help.
you can use file reader to get base64 and set it as the image source :
<script>
axios.get('https://www.instagram.com/p/B_zZCRpB895/media/?size=t', {responseType: "blob"})
.then(function (response) {
var reader = new window.FileReader();
reader.readAsDataURL(response.data);
reader.onload = function () {
document.getElementById("imgsrc").src = reader.result;
}
});
</script>
Is there a particular reason you are retrieving this via an AJAX call using axios?
The endpoint you provided returns an image source already. To make it appear in the image element all you need to do is set the src to the endpoint URL as shown below. Unless you need to run a process to do something to the image you don't need to get the data as an array buffer.
document.getElementById("imgsrc").src = "https://www.instagram.com/p/B_zZCRpB895/media/?size=t";
I have a Form in ReactJs and I want to submit both data and files to my php API ( Yii2) endpoint. (I do not want to use the raw Input file upload form as I want to have functions like file preview, cropping and most importantly progress bar on file upload)
After doing some research, I came across Uppy which seems to be a great tool to help in this task. I have been going through the docs and other materials for a few days now.
I have written a function to upload files using uppy file uploader following tutorials such as https://uppy.io/docs/react/. My function is very buggy as
I do not even see thumbnails generated from files uploaded, I do not see any information on my DragDrop Component.
I am not able to upload the files to my Yii2 API endpoint. I get the error Reason:
CORS header ‘Access-Control-Allow-Origin’ missing with results such
as: Object { successful: [], failed: (1) […], uploadID:
"cjs3mua0g0001245zctq3nbqa" }
Here is my code for the uppy function
AvatarPicker(currentAvatar ){
const {user} = this.props
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: user.username
})
};
const uppy = Uppy({ autoProceed: true })
.use(Dashboard, { trigger: '#select-files' })
.use(GoogleDrive, { target: Dashboard, serverUrl: apiConstants.API_GENERAL_URL+'changeprofilepic' })
.use(Instagram, { target: Dashboard, serverUrl: apiConstants.API_GENERAL_URL+'changeprofilepic' })
.use(Webcam, { target: Dashboard })
.use(Tus, { endpoint: apiConstants.API_GENERAL_URL+'changeprofilepic?access-token='+user.username, requestOptions })
.on('complete', (result) => {
console.log('Upload result:', result)
})
return (
<div>
<img src={currentAvatar} alt="Current Avatar" />
<DragDrop
uppy={uppy}
locale={{
strings: {
// Text to show on the droppable area.
// `%{browse}` is replaced with a link that opens the system file selection dialog.
dropHereOr: 'Drop here or %{browse}',
// Used as the label for the link that opens the system file selection dialog.
browse: 'browse'
}
}}
/>
</div>
)
And in my component render function, I call the AvatarPicker class as show
{
this.AvatarPicker('./../images/master.png')
}
Any heads up on this issue, propose solutions, fixes or new Ideas to get around my task is highly appreciated.
I'm attempting to write a small image proxier script on my website, because imgur is blocked on my current network and want to be able to see images from Stack Overflow.
I've got this code on my personal website:
$image = $_GET['url'];
$imageData = base64_encode(file_get_contents($image));
echo '<img src="data:image/jpeg;base64,'.$imageData.'">';
This should take the URL of an image, have my server download the image and then display it (by itself) on the page.
This works, for example, if I was trying to proxy my Stack Overflow account profile picture, I could use this link, which, as you can see works totally fine to display the picture on the page. I can see this image even on my blocked network.
Now, I've created a userscript that automatically transverses all images and links on a loaded page, and switches it's source/href link with a proxied version.
This is the part that is not working for me, when supplied with a proxied link, the image does not show in the element.
Here is my userscript:
function runProxier() {
$('img').each(function() {
var image = $(this);
if(!image.data('image_proxier_converted')) {
image.attr('src', getProxyLink(image.attr('src')));
image.attr('data-image_proxier_converted', 1);
}
});
$('a').each(function() {
var link = $(this);
if(!link.data('image_proxier_converted')) {
link.attr('href', getProxyLink(link.attr('href')));
link.attr('data-image_proxier_converted', 1);
}
});
}
function getProxyLink(givenLink) {
if (givenLink) {
if (replace_from.some(function(v) {
return givenLink.indexOf(v) >= 0;
})) {
return proxy_link + encodeURI(givenLink);
} else {
return givenLink;
}
}
}
When ran on my example, my profile picture, the link is properly converted.
<img src="//grumpycrouton.com/other/image_proxy/?url=https://i.stack.imgur.com/YkRwP.png?s=48&g=1" alt="" width="24" height="24" class="-avatar js-avatar-me" data-image_proxier_converted="1">
But the image does not show, it's still blank in my menu bar.
Why is my image not displayed?
I was able to resolve this problem by using this code on my server:
<?php
if(!isset($_GET['url'])) {
die('No image given');
}
header('Content-Type: image/jpeg');
readfile($_GET['url']);
?>
The header() call tells the client that it should serve an image, and readfile() will download (but not store on my server) and display the image.
I also noticed my URL was not properly encoding to be sent to the server, so I altered my userscript like so:
function getProxyLink(givenLink) {
if (givenLink) {
if (replace_from.some(function(v) {
return givenLink.indexOf(v) >= 0;
})) {
var new_link = proxy_link + encodeURIComponent(givenLink);
console.log(new_link);
return new_link;
} else {
return givenLink;
}
}
}
I am trying to render an image using php for my website that will dynamically display images straight from the Google Places API (Reference https://developers.google.com/places/web-service/photos?hl=en)
The image source looks like the following example:
https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=CnRtAAAATLZNl354RwP_9UKbQ_5Psy40texXePv4oAlgP4qNEkdIrkyse7rPXYGd9D_Uj1rVsQdWT4oRz4QrYAJNpFX7rzqqMlZw2h2E2y5IKMUZ7ouD_SlcHxYq1yL4KbKUv3qtWgTK0A6QbGh87GB3sscrHRIQiG2RrmU_jF4tENr9wGS_YxoUSSDrYjWmrNfeEHSGSc3FyhNLlBU&key=API_KEY
If you visit this URL via your browser it will render an image and this is no longer the URL you see.
My issue is that when viewing the page source, this is exactly the image source URL you see which is bad because my key is then publicized. What is the proper way to render images while keeping my key private? I have searched the API and the web for this but to no avail. I did see some tricks using file_get_contents and file_put_contents but my web host does not allow that. Finally, saving the images is against the api rules so that is not an option.
Any tips would be appreciated. Thanks in advance.
You may send a HEAD-request to the particular URL and extract the content of the Location-header:
<?php
$context = stream_context_create(array('http' =>array('method'=>'HEAD')));
$fp = fopen('desiredPlacesApiImgUrl', 'rb', false, $context);
$meta = stream_get_meta_data($fp);
if(isset($meta['wrapper_data'])){
$location=preg_grep('#^\s*Location:#',$meta['wrapper_data']);
if(count($location)){
$imgUrl=trim(preg_replace('#^Location:#i','',reset($location)));
die($imgUrl);//the desired img-url
}
}
fclose($fp);
?>
But when file_get_contents isn't allowed on your server I'm afraid fopen also isn't allowed for external URLs.
Another option: use the Maps-Javascript-API, request the place and the response should contain the desired URL (without using any key).
Demo:
function loadPlacePhotos() {
var photos = document.querySelectorAll('img[data-place]'),
service = new google.maps.places
.PlacesService(document.createElement('div'));
for (var i = 0; i < photos.length; ++i) {
(function(photo) {
service.getDetails({
placeId: photo.getAttribute('data-place')
}, function(r) {
if (r.photos.length) {
google.maps.event.addDomListener(photo, 'click', function() {
photo.setAttribute('src', r.photos[0].getUrl({
maxHeight: 100
}));
photo.style.visibility = 'visible';
if (r.photos.length > 1) {
r.photos.push(r.photos.shift());
photo.setAttribute('title', 'click to see next photo');
photo.style.cursor = 'pointer';
} else {
google.maps.event.clearListeners(photo, 'click');
}
});
google.maps.event.trigger(photo, 'click');
}
});
}(photos[i]));
}
}
body::before {
content: url(https://maps.gstatic.com/mapfiles/api-3/images/powered-by-google-on-white2.png);
}
img[data-place] {
visibility: hidden;
display: block;
}
<ul>
<li>
Google: Mountain View
<img data-place="ChIJj61dQgK6j4AR4GeTYWZsKWw" />
</li>
<li>
Google: Sydney
<img data-place="ChIJN1t_tDeuEmsRUsoyG83frY4" />
</li>
<li>
Google: Berlin
<img data-place="ChIJReW1rcRRqEcRaY3CuKBdqZE" />
</li>
</ul>
<script defer src="https://maps.googleapis.com/maps/api/js?v=3&libraries=places&callback=loadPlacePhotos"></script>
The demo uses a custom attribute for images data-place which will be assigned to a placeId of a particular place. It parses these images, requests the photos and displays them(when there ar more than 1 photo the user can switch between the photos by clicking on the image )
However, it must not be a problem when your key is visible, set the allowed referers for your (browser)-key and you can use the key without a risk on your own domain.