WWW::Mechanize : How to upload file under different file name? - perl

How to make WWW::Mechanize upload file under different file name?
I would like web server to see/record file name different from file name on my computer.

my $file = [
'filename-on-disk.txt', # The file you'd like to upload.
'filename-for-upload.txt', # The filename you'd like to give the web server.
'Content-type' => 'text/plain' # Any other flags you'd like to add go here.
];
$mech->post("http://example.com/upload.cgi", [
'upload' => $file
]);
Taken from:
https://gist.github.com/gaurav/253111#file-file-upload-pl

You can use a hard link:
link "file_name_on_your_computer","desired_new_name";
# Code to upload the newly created link
unlink "desired_new_name";
Notes
You need not worry about disk space usage if you're using a large file: the file is not duplicated, the hard link is simply a new name for the same inode.
This solution is limited to just those filesystems that support hard links. If you're on Windows, this may end up creating and uploading only a shortcut to your original file.

Related

How can I export cached files saved in a browser using CacheStorage?

I have a website which uses the CacheStorage API to save various files using a Service Worker. For reasons beyond my control, lots of these files have been lost from the server they get loaded from. However, I have just realised that several hundred of the files have been cached locally in a browser which had accessed the site lots over a period of years (Luckily the site hadn't been clearing up the cache after itself properly). I can preview the files using chrome's dev tools, but when I click "download" it attempts to download a copy from the server (which no longer exists), rather than giving me the locally cached version.
What's the simplest way to do a one-off export of these files (bearing in mind there's a few hundred of them)? I have full access to the computer the browser is running on, and the domain that the site / service worker is running on. It doesn't need to be a pretty solution, as once the files are restored I plan to learn plenty of lessons to prevent something similar happening in future.
The CacheStorage API can be accessed from normal web page JavaScript, as well as a service worker, so if you create a web page on the server that accesses window.caches, you should be able to fetch things out of the cache and do whatever you want. Once you have cache.keys() you could loop over that and use match() which returns the response for that request. You could then print them out for copy and paste (presumably not ideal), POST each one to a server that saves them, or similar.
Here is some normal JS I have on traintimes.org.uk; only to display a list of offline pages, but it could presumably fetch the actual cache entries if it needed.
<script>
// Open the page cache
caches.open("pages")
// Fetch its keys (cached requests)
.then(cache => cache.keys())
// We only want the URLs of each request
.then(reqs => reqs.map(r => r.url))
// We want most recent one first (reverse is in-place)
.then(urls => (urls.reverse(), urls))
// We don't care about the domain name
.then(urls => urls.map(u => u.replace(/^.*?uk/, '')))
// We want them to be clickable links
.then(urls => urls.map(u => [
'<a href="', u, '">',
u.replace(/\?cookie=[^;&]*/, ''),
'</a>'].join("")))
// We want them to be visible on the page
.then(urls =>
document.getElementById('offline-list').innerHTML =
'<li>' + urls.join('</li><li>') + '</li>'
);
</script>
Responses added to the CacheStorage API are stored on disk. For example, chrome on Mac OSX stores them in
~/Library/Application Support/Google/Chrome/Default/Service Worker/CacheStorage. Inside this directory, there is a directory for each domain, and within those, separate directories for each particular cache used by that domain. The names of these directories (at both levels) don't appear to be human-readable, so you may need to search the contents to find the specific cache you're looking for.
Within the directory for each cache, every response is saved in a different file. These are binary files and contain various bits of info, including the URL requested (near the top) and the HTTP response headers (towards the end). Between these, you'll find the body of the HTTP response.
The exact logic for extracting the bodies and saving them to files usable elsewhere will vary based URL schemas, file formats etc. This bash script worked for me:
#!/bin/bash
mkdir -p export
for file in *_0
do
output=`LC_ALL=C sed -nE 's%^.*/music/images/artists/542x305/([^\.]*\.jpg).*%\1%p;/jpg/q' $file`
if [ -z "$output" ]
then
echo "file $file missing music URL"
continue
fi
if [[ $(LC_ALL=C sed -n '/x-backend-status.*404/,/.*/p' $file) ]]
then
echo "$file returned a 404"
continue
fi
path="export/$output"
cat $file | LC_ALL=C sed -n '/music\/images\/artists/,$p' | LC_ALL=C sed 's%^.*/music/images/artists/542x305/[^\.]*\.jpg%%g' | LC_ALL=C sed -n '/GET.*$/q;p' > $path
echo "$file -> $path"
done

Perl Net::FTP not lists particular file

I am trying to list the file of remote host using Net::FTP Perl module. Later I want to download it using put command.
Will it possible to list the particular file using ls command
Syntax I am using is:
$remote_dir = "/home/user/test_dir/";
$ftp->cwd($remote_dir);
$file_name = "test.txt";
print $ftp->ls($file_name);
This file is exists in remote server when I tried checking it manually. But listing is not happening.
ftp->ls(); is used for only listing the directory contents or can it be used to list the particular file from a directory as I mentioned above?
ftp->ls(); is used for only listing the directory contents or can it be used to list the particular file from a directory
From the documentation:
ls ( [ DIR ] )
Get a directory listing of DIR, or the current directory.
Thus, it is clearly documented to list a directory, not a specific regular file.

Download file from Google Drive with PowerShell

In trying to download a file with PowerShell I have the following
$client = new-object System.Net.WebClient
$client.DownloadFile($AGRIDATAMISCURL,$TESTAGRIDATAMISCZIP)
Where $AGRIDATAMISCURL is a URL that looks like "https://drive.google.com/file/d/<...>" and $TESTAGRIDATAMISCZIP looks like "C:\test\A.zip"
This script doesn't return an error but the file it downloads is basically an HTML file with a prompt to sign in to Google. Is there another way to download a file that is "shared with me"?
Share the file first
Files in Google Drive must be made available for sharing before they can be downloaded. There's no security context when running from PowerShell, so the file download fails. (To check this, rename the file with a `.html` extension, and view in a text editor).
Note: the following solution assumes that the links are to non-security-critical files, or that the links will only be given to those with whom access can be trusted (links are https, so are encrypted with transmission). The alternative is to programatically authenticate with Google - something not addressed in this answer.
To Share the file, in Google Drive:
Right-click the file, and choose Get shareable link
2. Turn link sharing on
Click Sharing Settings
Ensure that Anyone with the link can view (Note that in corporate environments, the link must be shared with those outside the organization in order to bypass having to login)
Then Download Programatically
Then, code can be used to download the file as such (in this case with Windows PowerShell):
# Download the file
$zipFile = "https://drive.google.com/uc?export=download&id=1cwwPzYjIzzzzzzzzzzzzzzzzzzzzzzzz"
Invoke-WebRequest -Uri $zipFile -OutFile "$($env:TEMP)\myFile.doc"
Replace the 1cwwPzYjIzzzzzzzzzzzzzzzzzzzzzzzz with the ID code from the shareable link setting back in step #2, above.

How to extract .gz file with .txt extension folder?

I'm currently stuck with this problem where my .gz file is "some_name.txt.gz" (the .gz is not visible, but can be recognized with File::Type functions),
and inside the .gz file, there is a FOLDER with the name "some_name.txt", which contains other files and folders.
However, I am not able to extract the archive as you would manually (the folder with the name "some_name.txt" is extracted along with its contents) when calling the extract function from the Archive::Extract because it will just extract the "some_name.txt" folder as a .txt file.
I've been searching the web for answers, but none are correct solutions. Is there a way around this?
From Archive::Extract official doc
"Since .gz files never hold a directory, but only a single file;"
I would recommend using tar on the folder and then gz it.
That way you can use Archive::Tar to easily extract specific file:
Example from official docs:
$tar->extract_file( $file, [$extract_path] )
Write an entry, whose name is equivalent to the file name provided to disk. Optionally takes a second parameter, which is the full native path (including filename) the entry will be written to.
For example:
$tar->extract_file( 'name/in/archive', 'name/i/want/to/give/it' );
$tar->extract_file( $at_file_object, 'name/i/want/to/give/it' );
Returns true on success, false on failure.
Hope this helps.
Maybe you can identify these files with File::Type, rename them with .gz extension instead of .txt, then try Archive::Extract on it?
A gzip file can only contain a single file. If you have an archive file that contains a folder plus multiple other files and folders, then you may have a gzip file that contains a tar file. Alternatively you may have a zip file.
Can you give more details on how the archive file was created and a listing of it contents?

Perl script to Hyperlink to open a file based on the name of the file in each cell

I had developed a perl script to look for matching strings from text files and copied it into a spread sheet, I had also included the text file name into the spreadsheet for corresponding matching string. Now I want to hyperlink to open the file by clicking the file name in each cell.
Any help would be much appreciated! I'm not much of a programmer... Thanks!
Here is some examples by using the Spreadsheet::WriteExcel
# External link to a local file
$worksheet->write('B2', 'external:Italy.xls');
# External link to a local file with worksheet
$worksheet->write('B3', 'external:Italy.xls#Sales!B3');
# External link to a local file with worksheet and alternative string
$worksheet->write('B4', 'external:Italy.xls#Sales!B4', 'Link');
# External link to a local file with worksheet and format
$worksheet->write('B5', 'external:Italy.xls#Sales!B5', $format);
# External link to a remote file, absolute path
$worksheet->write('B6', 'external:c:/Temp/Asia/China.xls');
# External link to a remote file, relative path
$worksheet->write('B7', 'external:../Asia/China.xls');
# External link to a remote file with worksheet
$worksheet->write('B8', 'external:c:/Temp/Asia/China.xls#Sales!B8');
# External link to a remote file with worksheet (with spaces in the name)
$worksheet->write('B9', q{external:c:/Temp/Asia/China.xls#'Product Data'!B9});
You can see the write API for more information.