The function navigator.canShare() encountered a permissions denial while running in Typescript

Currently, I am in the process of developing an Angular8 PWA and have successfully implemented webshare to share text content. To my excitement, Chrome has now extended its support for file sharing starting from May 2019.

However, while attempting to integrate file sharing in Typescript, I encountered a challenging error:

Error: NotAllowedError - Permission denied

let navigator: any;
navigator = window.navigator;
const title = "myTitle";
let data = {
  title: title,
  text: text,
  url: url,
  files: []
};
console.log(data);

if (navigator.share) {
  fetch(url)
    .then(res => res.blob()) 
    .then(file => {
      const fileName = data.text + ".mp3";
      const options = { type: "audio/mp3" };
      const newFile = new File([file], fileName, options);
      data.files.push(newFile);
      console.log(data);
//lastModified: 1564912016680
//lastModifiedDate: Sun Aug 04 2019 11:46:56 GMT+0200 (Central European //Summer Time) {}
//name: "myName.mp3"
//size: 40643
//type: "audio/mpeg"
//webkitRelativePath: ""
      if (navigator.canShare(data)) {
        navigator
          .share(data)
          .then(() => {})
          .catch(err => {
            console.error("Unsuccessful share " + err.message); //Here is where I encounter the Permissions denied error
          });
      }
    });

I'm uncertain whether the issue lies with how I retrieve the file (which seems correct) or with the canShare method call. I'm using Chrome on my mobile device. The provided fiddle functions properly on my phone, although it requires selecting a file. https://jsfiddle.net/ericwilligers/8cpuskqd/

The share functionality is connected to a button containing the link of the file to be shared.

Edit

Upon converting data.files from an array to an object, a new error message surfaces:

Error: TypeError - Failed to execute 'canShare' on 'Navigator': Iterator getter is not callable.

Edit2

To replicate the problem, I have created a codepen:

https://codepen.io/anon/pen/xvXvPZ

Answer №1

Success! It's working like a charm.


function shareContent(url, text) {
    let navigator: any;
    navigator = window.navigator;
    const title = "yourTitle";
    let data = { files: [], text: text, url: url, title: title };
    const options = { type: "audio/mp3" };

    this.http
      .get(url, {
        responseType: "arraybuffer"
      })
      .subscribe(response => {
        console.log(response);

        let blob = new File([response], `${text}.mp3`, options);
        data.files.push(blob);
        console.log(data);
        if (navigator.canShare(data)) {
          navigator
            .share(data)
            .then(() => {})
            .catch(err => {
              console.error("Unsuccessful share " + err);
            });
        }
      });
  }

Answer №2

To utilize the fetch method for asynchronous operations, follow the example below:

const shareNow = async () => {
  let imageResponse = await window.fetch('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png');
  let imageBuffer = await imageResponse.arrayBuffer();
  let fileArray = [new File([imageBuffer], "File Name", {
    type: "image/png",
    lastModified: Date.now()
  })];
  if(window.navigator && window.navigator.canShare && window.navigator.canShare({files: fileArray})){
    navigator.share({
      files: fileArray,
      title: 'Title',
      text: 'Text to show'
    }).then(() => {
      console.log('Thanks for sharing!');
    })
    .catch(console.error);
  }
}

Answer №3

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
const navigator = window.navigator as any;

@Component({
  selector: 'app-image-post',
  templateUrl: './image-post.component.html',
  styleUrls: ['./image-post.component.css']
})
export class ImagePostComponent {

  constructor(private http: HttpClient) {}

  // Function to share image as a post
  shareNow = async () => {
    console.log("Inside shareNow method....");
    if ('canShare' in navigator) {
      console.log("Inside if condition....");
      let img = 'assets/img/image-post-1.jpg';
      const share = async function () {
        try {
          const response = await fetch(img);
          const blob = await response.blob();
          const file = new File([blob], 'rick.jpg', { type: blob.type });
          await navigator.share({
            url: img,
            title: 'Image',
            text: 'Image',
            files: [file],
          });
          console.log("Shared successfully....");
        } catch (err) {
          console.log(err.name, err.message);
        }
      };
      share();
    }
  };
<html>
<head>
 <meta name="description" content="Web Share API demo">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<title>
    Web Share API
</title>

<body>
    <div>
        <div>
            <img src="assets/img/image-post-1.jpg" alt="" style="height: 26rem; width: 26rem;">
        </div>
        <div>
            <button (click)="shareNow()" id="shareFilesButton" style="background-color: blueviolet; color: white;">Share File</button>
        </div>
    </div>
</body>

</html>

Integrate this code to enable image sharing option. Note that navigation.share works only with HTTPS, not with HTTP servers. This is an Angular example for sharing images. The image is stored in the assets/img folder; ensure you use the correct image URL for sharing.

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Python Selenium does not output console.log messages

One issue I'm encountering is that when I run this Python script, I can't seem to see any of the console.log, console.error, console.warning messages in my logs: import time from selenium.webdriver.common.by import By from selenium.webdriver.supp ...

How can I prevent buttons from being created using ngFor in Angular?

I need help with creating an HTML table that includes a cell with a button and a dropdown generated using ngFor. How can I disable the buttons (generated via ngFor) if no value is selected from the dropdown? Here's what I have tried so far: In my App ...

Encountering a Typescript issue while trying to access two distinct values dynamically from within a single object

Currently, I'm developing a component library and facing an issue with a TypeScript error: An Element implicitly has an 'any' type due to the expression of type 'levelTypes | semanticTypes' being unable to index type '{ level1 ...

Assigning string properties to different types

I have numerous data types, each with a common property called dataType, and I am currently mapping each one to that specific value: interface GroupData { dataType: "group"; name: string; people: PersonData[]; } interface PersonData ...

A secure way to perform a deep update on any type, even if it is completely different from the original

Is there a method to eliminate the as any in the update_substate function? It seems type-safe when directly invoking the update_state function, so it should also be safe when invoked indirectly, right? These functions are meant to be lightweight helpers ...

Ensure that Serenity BDD preserves Browser Memory

@Managed(uniqueSession = true, clearCookies = Never) My Serenity app incorporates an OAuth login mechanism using Microsoft login. I have implemented the code above to ensure the browser retains memory, but I am encountering an issue. I want one test to lo ...

What is the best way to have text wrap around an icon in my React application?

I am facing an issue while trying to display the note description over the trash icon in a React app. I have tried various methods but can't seem to achieve the desired effect. Can anyone guide me on how to get this layout? Here is what I intend to a ...

Tips for efficiently saving data using await in Mongoose

Currently, the code above is functional, but I am interested in utilizing only async/await for better readability. So, my query is: How can I convert cat.save().then(() => console.log('Saved in db')); to utilize await instead? The purpose of ...

Tips for configuring the Index column within an Angular Mat-table (when the dataIndex displays 'NaN')

My Mat-Table is working perfectly, but I am looking for a way to add an auto-increment index. Below is the HTML code: <div class="mat-elevation-z8"> <table mat-table [dataSource]="dataSource" matSort> <ng-container matColumnDef="no"> ...

Version 4.0 of d3 introduces an import statement that provides a __moduleExports wrapper

Having difficulty with an import statement in my D3 4.0 and Ionic2/Angular2 project. I believe the import statement is correct, as everything compiles successfully. import * as d3Request from 'd3-request'; export class HomePage { construc ...

typescript api overlooking the async await functionality

My controller contains an asynchronous method that is supposed to set a results object. However, I'm facing an issue where instead of waiting for the 'await' to finish executing, the code jumps to the response object call prematurely, leavin ...

Is there a way to send map data using props in React?

I just want to store and pass the current props.url to the videomodal so I can show the same active video on the video modal. I can't use useState in the map. How can I pass it? Or is there any other solution? Videos.tsx ( props.url must be in the &l ...

Creating a redux store with an object using typescript: A step-by-step guide

Having recently started using Redux and Typescript, I'm encountering an error where the store is refusing to accept the reducer when working with objects. let store = createStore(counter); //error on counter Could this be due to an incorrect type set ...

Utilize Typescript/Javascript to utilize the Gmail API for sending emails via email

I am trying to send emails from my application using my Gmail account with Ionic. I have followed tutorials from SitePoint and Google Developers. Here is how I'm initializing the client: client_id: gapiKeys.client_id, discoveryDocs: ["https://www.goo ...

Triggering multiple subscription functions in Ionic 3 NGRX when a single state change occurs

I have developed an Ionic 3 application that utilizes NGRX for state management purposes. The app is designed to connect to a device via BLE technology. Within my connection page, where the BLE device is connected, I have implemented the following code: ...

What is the recommended way to include @types/module in a TypeScript project?

Once I've added a module like @types/express using npm, how can I correctly reference it in typescript? I've tried the following methods: /// <reference path="../node_modules/@types/express/index.d.ts" /> but I still get an error sayin ...

Ways to observe redux action flow within a component

I am currently developing a React application structured with the following elements: redux typesafe-actions redux-observable My query is: How can I trigger a UI action when a specific redux action occurs? For instance, if we have these asynchronous ac ...

Tips for retrieving information from a Vuetify modal window

Is it possible to retrieve data from a dialog in the VueJS Vuetify framework? Specifically, how can I access the username or password entered in the NewUserPopup.vue dialog from app.vue? App.vue = main template NewUserPopup.vue = Dialog template imported ...

What is causing the geolocation heading to remain "null" on Android devices when using Chrome?

Recently, I developed a compact geolocation watch using the following code snippet: navigator.geolocation.watchPosition( this.updateLocation.bind(this), this.errorLocation.bind(this), {enableHighAccuracy: true} ); The function updateLocation ...

The type 'ReadableStream<any>' cannot be assigned to the parameter type 'ReadableStream'

Is there a way to convert a Blob into a Readable format? import {Readable} from 'stream'; const data: Blob = new Blob( ); const myReadable: Readable = (new Readable()).wrap(data.stream()); myReadable.pipe(ext); Encountering an error: ERROR in s ...