diff --git a/ui/component/fileActions/index.js b/ui/component/fileActions/index.js
index 0e15bb7ea..f6e17a4bc 100644
--- a/ui/component/fileActions/index.js
+++ b/ui/component/fileActions/index.js
@@ -7,12 +7,13 @@ import {
   selectMyChannelClaims,
   makeSelectClaimIsStreamPlaceholder,
   makeSelectTagInClaimOrChannelForUri,
+  makeSelectStreamingUrlForUri,
 } from 'lbry-redux';
 import { DISABLE_COMMENTS_TAG } from 'constants/tags';
 import { makeSelectCostInfoForUri } from 'lbryinc';
-import { doSetPlayingUri } from 'redux/actions/content';
+import { doSetPlayingUri, doPlayUri } from 'redux/actions/content';
 import { doToast } from 'redux/actions/notifications';
-import { doOpenModal, doSetActiveChannel, doSetIncognito } from 'redux/actions/app';
+import { doOpenModal, doSetActiveChannel, doSetIncognito, doAnalyticsView } from 'redux/actions/app';
 import fs from 'fs';
 import FileActions from './view';
 import { makeSelectFileRenderModeForUri } from 'redux/selectors/content';
@@ -26,6 +27,7 @@ const select = (state, props) => ({
   myChannels: selectMyChannelClaims(state),
   isLivestreamClaim: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
   reactionsDisabled: makeSelectTagInClaimOrChannelForUri(props.uri, DISABLE_COMMENTS_TAG)(state),
+  streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state),
 });
 
 const perform = (dispatch) => ({
@@ -42,6 +44,7 @@ const perform = (dispatch) => ({
   },
   clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })),
   doToast: (options) => dispatch(doToast(options)),
+  download: (uri) => dispatch(doPlayUri(uri, false, true, () => dispatch(doAnalyticsView(uri)))),
 });
 
 export default connect(select, perform)(FileActions);
diff --git a/ui/component/fileActions/view.jsx b/ui/component/fileActions/view.jsx
index caafded69..6b1f3a981 100644
--- a/ui/component/fileActions/view.jsx
+++ b/ui/component/fileActions/view.jsx
@@ -1,5 +1,5 @@
 // @flow
-import { SIMPLE_SITE, SITE_NAME, ENABLE_FILE_REACTIONS } from 'config';
+import { SITE_NAME, ENABLE_FILE_REACTIONS } from 'config';
 import * as PAGES from 'constants/pages';
 import * as MODALS from 'constants/modal_types';
 import * as ICONS from 'constants/icons';
@@ -13,6 +13,9 @@ import ClaimSupportButton from 'component/claimSupportButton';
 import ClaimCollectionAddButton from 'component/claimCollectionAddButton';
 import { useHistory } from 'react-router';
 import FileReactions from 'component/fileReactions';
+import { Menu, MenuButton, MenuList, MenuItem } from '@reach/menu-button';
+import Icon from 'component/common/icon';
+import { webDownloadClaim } from 'util/downloadClaim';
 
 type Props = {
   uri: string,
@@ -28,6 +31,8 @@ type Props = {
   clearPlayingUri: () => void,
   isLivestreamClaim: boolean,
   reactionsDisabled: boolean,
+  download: (string) => void,
+  streamingUrl: ?string,
 };
 
 function FileActions(props: Props) {
@@ -45,6 +50,8 @@ function FileActions(props: Props) {
     doToast,
     isLivestreamClaim,
     reactionsDisabled,
+    download,
+    streamingUrl,
   } = props;
   const {
     push,
@@ -57,6 +64,8 @@ function FileActions(props: Props) {
   const claimId = claim && claim.claim_id;
   const { signing_channel: signingChannel } = claim;
   const channelName = signingChannel && signingChannel.name;
+  const fileName = claim && claim.value && claim.value.source && claim.value.source.name;
+
   // We want to use the short form uri for editing
   // This is what the user is used to seeing, they don't care about the claim id
   // We will select the claim id before they publish
@@ -76,6 +85,22 @@ function FileActions(props: Props) {
   const urlParams = new URLSearchParams(search);
   const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID);
 
+  // @if TARGET='web'
+  const [downloadClicked, setDownloadClicked] = React.useState(false);
+
+  function handleWebDownload() {
+    // download() causes 'streamingUrl' to be populated.
+    download(uri);
+    setDownloadClicked(true);
+  }
+
+  React.useEffect(() => {
+    if (downloadClicked && streamingUrl) {
+      webDownloadClaim(streamingUrl, fileName);
+    }
+  }, [downloadClicked, streamingUrl, fileName]);
+  // @endif
+
   function handleRepostClick() {
     if (!hasChannels) {
       clearPlayingUri();
@@ -114,7 +139,9 @@ function FileActions(props: Props) {
 
   const rhsSection = (
     <>
-      {!SIMPLE_SITE && <FileDownloadLink uri={uri} />}
+      {/* @if TARGET='app' */}
+      <FileDownloadLink uri={uri} />
+      {/* @endif */}
       {claimIsMine && (
         <Button
           className="button--file-action"
@@ -135,14 +162,38 @@ function FileActions(props: Props) {
           onClick={() => openModal(MODALS.CONFIRM_FILE_REMOVE, { uri })}
         />
       )}
-      {!claimIsMine && (
-        <Button
-          title={__('Report content')}
+      <Menu>
+        <MenuButton
           className="button--file-action"
-          icon={ICONS.REPORT}
-          navigate={`/$/${PAGES.REPORT_CONTENT}?claimId=${claimId}`}
-        />
-      )}
+          onClick={(e) => {
+            e.stopPropagation();
+            e.preventDefault();
+          }}
+        >
+          <Icon size={20} icon={ICONS.MORE} />
+        </MenuButton>
+        <MenuList className="menu__list">
+          {/* @if TARGET='web' */}
+          <MenuItem className="comment__menu-option" onSelect={handleWebDownload}>
+            <div className="menu__link">
+              <Icon aria-hidden icon={ICONS.DOWNLOAD} />
+              {__('Download')}
+            </div>
+          </MenuItem>
+          {/* @endif */}
+          {!claimIsMine && (
+            <MenuItem
+              className="comment__menu-option"
+              onSelect={() => push(`/$/${PAGES.REPORT_CONTENT}?claimId=${claimId}`)}
+            >
+              <div className="menu__link">
+                <Icon aria-hidden icon={ICONS.REPORT} />
+                {__('Report content')}
+              </div>
+            </MenuItem>
+          )}
+        </MenuList>
+      </Menu>
     </>
   );
 
diff --git a/ui/component/fileDownloadLink/view.jsx b/ui/component/fileDownloadLink/view.jsx
index 670048df1..7f2194a0e 100644
--- a/ui/component/fileDownloadLink/view.jsx
+++ b/ui/component/fileDownloadLink/view.jsx
@@ -3,6 +3,7 @@ import * as ICONS from 'constants/icons';
 import * as MODALS from 'constants/modal_types';
 import React, { useState } from 'react';
 import Button from 'component/button';
+import { webDownloadClaim } from 'util/downloadClaim';
 
 type Props = {
   uri: string,
@@ -46,16 +47,7 @@ function FileDownloadLink(props: Props) {
   // @if TARGET='web'
   React.useEffect(() => {
     if (didClickDownloadButton && streamingUrl) {
-      let element = document.createElement('a');
-      element.setAttribute('href', `${streamingUrl}?download=true`);
-      element.setAttribute('download', fileName);
-      element.style.display = 'none';
-      // $FlowFixMe
-      document.body.appendChild(element);
-      element.click();
-      // $FlowFixMe
-      document.body.removeChild(element);
-
+      webDownloadClaim(streamingUrl, fileName);
       setDidClickDownloadButton(false);
     }
   }, [streamingUrl, didClickDownloadButton, fileName]);
diff --git a/ui/util/downloadClaim.js b/ui/util/downloadClaim.js
new file mode 100644
index 000000000..195a1bb20
--- /dev/null
+++ b/ui/util/downloadClaim.js
@@ -0,0 +1,13 @@
+export function webDownloadClaim(streamingUrl, fileName) {
+  // @if TARGET='web'
+  let element = document.createElement('a');
+  element.setAttribute('href', `${streamingUrl}?download=true`);
+  element.setAttribute('download', fileName);
+  element.style.display = 'none';
+  // $FlowFixMe
+  document.body.appendChild(element);
+  element.click();
+  // $FlowFixMe
+  document.body.removeChild(element);
+  // @endif
+}