Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to correctly save a file generated from the webpage inside a particular folder using local chrome (not chromium) #497

Closed
tlecoz opened this issue May 7, 2021 · 16 comments
Labels
issue: bug report A bug has been reported needs triage

Comments

@tlecoz
Copy link

tlecoz commented May 7, 2021

Since yesterday, I'm trying to save a file created in the webpage inside a particular folder (another folder than the "download" folder of windows).

I first tryed something like this :

[Puppetee]

this.page.exposeFunction("saveFile",(filePath:string,content:string)=>{
            return new Promise((onFileCreated,onError)=>{
                fs.appendFile(filePath, Buffer.from(content), (err)=>{
                    if (err) onError(err);
                    else onFileCreated("file saved");
             })  
       })
 })

[/Puppeteer]

[Webpage]

let path = "./tmp/test.fmp4";
blob.text().then((data)=>{
            window["saveFile"](path,data).then((msg:string)=>{
                console.log(msg);
            }).catch((e)=>{
                console.log("File not saved => ",e);
            })
  })

[/Webpage]

This code works but the file saved is broken. It's not the same result than what I get doing this

[Webpage]

var a = document.createElement("a");
 document.body.appendChild(a);
 (a as any).style = "display: none";
 a.href = window.URL.createObjectURL(blob);;
 a.download = fileName;
 a.click();
 window.URL.revokeObjectURL(a.href);

[/Webpage]

Instead of blob.text() , I tryed FileReader.readAsText and FileReader.readAsBinaryString but I get the exact same problem : the file is saved but it's broken.

When I download the file using a.href, the file is correct , so I searched a way to modify the path of the folder where the files are downloaded. I need to get this file inside my project because I have to process it with ffmpeg after that and ffmpeg doesn't like absolute path...

I found someone on the internet who posted that code as a solution to my problem :

[Puppeteer]
await page._client.send('Page.setDownloadBehavior', {behavior: 'allow', downloadPath: './tmp'});
[/Puppeteer]

But after I'll add this line, the download of my file failed. Not good.

So I searched more and found that code based on puppeteer-extra

[Puppeteer]

const puppeteer = require('puppeteer-extra');
import * as UserPreferencesPlugin from 'puppeteer-extra-plugin-user-preferences';
puppeteer.use(UserPreferencesPlugin({
  userPrefs: {
    download: {
      prompt_for_download: false,
      default_directory: '/tmp',
    }
  }
}));

[/Puppeteer]

But it doesn't work.................................
My file is downloaded inside the "download" folder of windows.

I do not know what to do now...
I thought saving a file was a common task but I tryed and tryed and tryed for almost 10 hours now ...

Here is how I launch Puppeteer just in case it helps you to help me :)

[Puppeteer]

const puppeteer = require('puppeteer-extra');
import * as UserPreferencesPlugin from 'puppeteer-extra-plugin-user-preferences';
puppeteer.use(UserPreferencesPlugin({
  userPrefs: {
    download: {
      prompt_for_download: false,
      default_directory: '/tmp',
    }
  }
}));

let browserConfig = {
   executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
   headless:false,
   devtools:true,
    args:["--enable-blink-features=WebCodecs",
             "--enable-experimental-web-platform-features",
             "--file-handling-api"
             ]
    }
    let pageViewport = {
         width:800,
         height:450,
         deviceScaleFactor:1
     }
     const browser = await puppeteer.launch(browserConfig); 
        
     this.page = await browser.newPage();
     this.page.setViewport(pageViewport)
     this.page.goto(urlOfMyWebPage);    

[/Puppeteer]

and my package.json looks like this

[package.json]

{
  "name": "puppeteer",
  "version": "9.1.1",
  "description": "A high-level API to control headless Chrome over the DevTools Protocol",
  "main": "./cjs-entry.js",
  "types": "lib/types.d.ts",
  "repository": "github:puppeteer/puppeteer",
  "engines": {
    "node": ">=10.18.1"
  },
  "scripts": {
    "test-browser": "wtr",
    "test-browser-watch": "wtr --watch",
    "unit": "npm run tsc-cjs && mocha --config mocha-config/puppeteer-unit-tests.js",
    "unit-debug": "npm run tsc-cjs && mocha --inspect-brk --config mocha-config/puppeteer-unit-tests.js",
    "unit-with-coverage": "cross-env COVERAGE=1 npm run unit",
    "assert-unit-coverage": "cross-env COVERAGE=1 mocha --config mocha-config/coverage-tests.js",
    "funit": "cross-env PUPPETEER_PRODUCT=firefox npm run unit",
    "test": "npm run tsc && npm run lint --silent && npm run unit-with-coverage && npm run test-browser",
    "prepare": "node typescript-if-required.js",
    "prepublishOnly": "npm run build",
    "dev-install": "npm run tsc && node install.js",
    "install": "node install.js",
    "eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)",
    "eslint-fix": "eslint --ext js --ext ts --fix .",
    "commitlint": "commitlint --from=HEAD~1",
    "markdownlint": "prettier --check **/README.md docs/api.md docs/troubleshooting.md",
    "markdownlint-fix": "prettier --write **/README.md docs/api.md docs/troubleshooting.md",
    "lint": "npm run eslint && npm run build && npm run doc && npm run commitlint && npm run markdownlint",
    "doc": "node utils/doclint/cli.js",
    "clean-lib": "rimraf lib",
    "build": "npm run tsc && npm run generate-d-ts",
    "tsc": "npm run clean-lib && tsc --version && npm run tsc-cjs && npm run tsc-esm",
    "tsc-cjs": "tsc -b src/tsconfig.cjs.json",
    "tsc-esm": "tsc -b src/tsconfig.esm.json",
    "apply-next-version": "node utils/apply_next_version.js",
    "test-install": "scripts/test-install.sh",
    "generate-d-ts": "api-extractor run --local --verbose",
    "generate-docs": "npm run generate-d-ts && api-documenter markdown -i temp -o new-docs",
    "ensure-correct-devtools-protocol-revision": "ts-node -s scripts/ensure-correct-devtools-protocol-package",
    "test-types-file": "ts-node -s scripts/test-ts-definition-files.ts",
    "release": "node utils/remove_version_suffix.js && standard-version --commit-all"
  },
  "files": [
    "lib/types.d.ts",
    "lib/**/*.d.ts",
    "lib/**/*.d.ts.map",
    "lib/**/*.js",
    "lib/**/*.js.map",
    "install.js",
    "typescript-if-required.js",
    "cjs-entry.js",
    "cjs-entry-core.js"
  ],
  "author": "The Chromium Authors",
  "license": "Apache-2.0",
  "dependencies": {
    "debug": "^4.1.0",
    "devtools-protocol": "0.0.869402",
    "extract-zip": "^2.0.0",
    "https-proxy-agent": "^5.0.0",
    "node-fetch": "^2.6.1",
    "pkg-dir": "^4.2.0",
    "progress": "^2.0.1",
    "proxy-from-env": "^1.1.0",
    "rimraf": "^3.0.2",
    "tar-fs": "^2.0.0",
    "unbzip2-stream": "^1.3.3",
    "ws": "^7.2.3"
  },
  "devDependencies": {
    "@commitlint/cli": "^11.0.0",
    "@commitlint/config-conventional": "^11.0.0",
    "@microsoft/api-documenter": "^7.12.7",
    "@microsoft/api-extractor": "^7.13.1",
    "@types/debug": "0.0.31",
    "@types/mime": "^2.0.0",
    "@types/mocha": "^7.0.2",
    "@types/node": "^14.0.13",
    "@types/proxy-from-env": "^1.0.1",
    "@types/rimraf": "^2.0.2",
    "@types/sinon": "^9.0.4",
    "@types/tar-fs": "^1.16.2",
    "@types/ws": "^7.2.4",
    "@typescript-eslint/eslint-plugin": "^4.4.0",
    "@typescript-eslint/parser": "^4.4.0",
    "@web/test-runner": "^0.12.15",
    "commonmark": "^0.28.1",
    "cross-env": "^7.0.2",
    "eslint": "^7.10.0",
    "eslint-config-prettier": "^6.12.0",
    "eslint-plugin-import": "^2.22.0",
    "eslint-plugin-mocha": "^8.0.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-unicorn": "^22.0.0",
    "esprima": "^4.0.0",
    "expect": "^25.2.7",
    "husky": "^4.3.0",
    "jpeg-js": "^0.3.7",
    "mime": "^2.0.3",
    "minimist": "^1.2.0",
    "mocha": "^8.2.0",
    "ncp": "^2.0.0",
    "pixelmatch": "^4.0.2",
    "pngjs": "^5.0.0",
    "prettier": "^2.1.2",
    "sinon": "^9.0.2",
    "source-map-support": "^0.5.19",
    "standard-version": "^9.0.0",
    "text-diff": "^1.0.1",
    "ts-node": "^9.0.0",
    "typescript": "^4.1.5"
  },
  "husky": {
    "hooks": {
      "commit-msg": "commitlint --env HUSKY_GIT_PARAMS"
    }
  }
}

[/package.json]

Please help me ! I'm becoming totally crazy !

@tlecoz tlecoz added issue: bug report A bug has been reported needs triage labels May 7, 2021
@berstend
Copy link
Owner

berstend commented May 7, 2021

This is unreadable, please provide a small, self-contained script (stripped to the essentials) that showcases the issue. :-)

@berstend
Copy link
Owner

berstend commented May 7, 2021

Ah, you were the one commenting in the previous issue: #44 (comment)

Did you try a minimal/new script with just the code mentioned in that issue?

@tlecoz
Copy link
Author

tlecoz commented May 7, 2021

Ok, shortly, I want this to work as expected :

const puppeteer = require('puppeteer-extra');
import * as UserPreferencesPlugin from 'puppeteer-extra-plugin-user-preferences';
puppeteer.use(UserPreferencesPlugin({
  userPrefs: {
    download: {
      prompt_for_download: false,
      default_directory: '/tmp',
    }
  }
}));

My file is still downloaded in the "download" folder of windows

@berstend
Copy link
Owner

berstend commented May 7, 2021

PPS: Seems like you're running on Windows - I doubt that /tmp would work for you.

@berstend
Copy link
Owner

berstend commented May 7, 2021

Tip: You can just check the Preferences file your regular browser creates and see what data is written there.

@tlecoz
Copy link
Author

tlecoz commented May 7, 2021

"tmp" is the name of my folder. But it doesn't work with another name neither
I just created a folder called "myDownloads" and updated the code to

const puppeteer = require('puppeteer-extra');
import * as UserPreferencesPlugin from 'puppeteer-extra-plugin-user-preferences';
puppeteer.use(UserPreferencesPlugin({
  userPrefs: {
    download: {
      prompt_for_download: false,
      default_directory: '/myDownloads',
    }
  }
}));

But it didn't change anything

@tlecoz
Copy link
Author

tlecoz commented May 7, 2021

Tip: You can just check the Preferences file your regular browser creates and see what data is written there.

I don't understand (?)

@berstend
Copy link
Owner

berstend commented May 7, 2021

"tmp" is the name of my folder.

Folders starting with a / are absolute not relative, this won't work.

I don't understand (?)

chrome://version/ => Profile path => Preferences file

@tlecoz
Copy link
Author

tlecoz commented May 7, 2021

"tmp" is the name of my folder.

Folders starting with a / are absolute not relative, this won't work.

I don't understand (?)

chrome://version/ => Profile path > Preferences files

Ok , I just updated the code like that

const puppeteer = require('puppeteer-extra');
import * as UserPreferencesPlugin from 'puppeteer-extra-plugin-user-preferences';
puppeteer.use(UserPreferencesPlugin({
  userPrefs: {
    download: {
      prompt_for_download: false,
      default_directory: './myDownloads',
    }
  }
}));

But it doesn"t work neither.

Concerning the preference, it's not a good solution because when my project will work, it will be deployed on dozens of servers, and I would like something that works without doing anything else , but thank you for your suggestion (and thank your for your reactivity ! )

@berstend
Copy link
Owner

berstend commented May 7, 2021

Concerning the preference, it's not a good solution because when my project will work, it will be deployed on dozens of servers,

Servers running Linux? Then you should run this in a docker container or on linux as well. My point was that you can use your regular Preferences file to find out how the default_directory path looks like.

@berstend
Copy link
Owner

berstend commented May 7, 2021

Just look at this:

executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',

I'm pretty sure your default_directory path needs to be absolute and be escaped as well.

@tlecoz
Copy link
Author

tlecoz commented May 7, 2021

My default_directory path looks like this
"C:\Users\fanth\Downloads"

"I'm pretty sure your default_directory path needs to be absolute and be escaped as well."
But in this page, the path is relative and the one who post it said it works... It would be preferable to have to relative path for me too
#44 (comment)

I just tryed with an absolute path to my folder and it worked !!!
Thank you for this !

What if I really want a relative path ?

@tlecoz
Copy link
Author

tlecoz commented May 7, 2021

(It's incredible how reactive you are ! Thank you so much for your help ! )

@berstend
Copy link
Owner

berstend commented May 7, 2021

There's no relative path in that thread. 😄 If you need a relative path why not use JS to dynamically generate an absolute path when instantiating the UserPreferencesPlugin?

@tlecoz
Copy link
Author

tlecoz commented May 7, 2021

If you need a relative path why not use JS to dynamically generate an absolute path when instantiating the UserPreferencesPlugin?

Nice idea, I will do that !

THANK YOU A LOT !

@berstend
Copy link
Owner

berstend commented May 7, 2021

Gonna close this for now, I recommend using https://extra.community for issues like this. :-)

@berstend berstend closed this as completed May 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
issue: bug report A bug has been reported needs triage
Projects
None yet
Development

No branches or pull requests

2 participants