Publishing my blog using HTTP upload in PHP

gabbersepp

Josef Biehler

Posted on January 25, 2020

Publishing my blog using HTTP upload in PHP

In the last article I wrote about how to publish a website with travis and FTP. First everything seemed fine but the nightly build suddenly failed. It took long time until I realized that this was not because of my code or my ftp server but because of how travis has setup it's network layers. Read on here if you are interested: https://blog.travis-ci.com/2018-07-23-the-tale-of-ftp-at-travis-ci

But the fight is not lost! My webspace paket includes a PHP instance and thus I am able to write a small HTTP upload tool. A bit oversized I think but it enables me to continue using my webspace bundle.

The PHP fileupload

Shame on me, it's been a long time since I programmed PHP. So I guess the following code is written very quick and dirty.

First I need a method for reading the HTTP Header to check a secret that I send along with the request.

// code/upload.php#L3-L19

function getRequestHeaders() {
    $headers = array();
    foreach($_SERVER as $key => $value) {
        if (substr($key, 0, 5) <> 'HTTP_') {
            continue;
        }
        $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
        $headers[$header] = $value;
    }
    return $headers;
}

$headers = getRequestHeaders();

if ($headers['Secret'] !== "<your secret>") {
    die("wrong secret");
}

The file can be accessed with $_FILES. To store the image somewhere, use move_uploaded_file.

// code/upload.php#L21-L22

move_uploaded_file($_FILES['zip-file']['tmp_name'], './'.$_FILES['zip-file']['name']);

It is very basic but should be enough to accept files from anywhere. To speed up the upload process I moved the whole /distdirectory into a ZIP archive. So I need to unzip it with PHP:

// code/upload.php#L23-L30

$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
    $zip->extractTo('./');
    $zip->close();
    echo 'ok';
} else {
    echo 'error duringunzip';
}

Zip & send the files with NodeJS

For zipping the files I use archiver and for making the upload request request.

archiver is very straightforward and only needs a few lines of code:

// code/zip.js

var fs = require('fs');
var archiver = require('archiver');

var fileName =   'test.zip'
var fileOutput = fs.createWriteStream(fileName);
const archive = archiver('zip');

fileOutput.on('close', function () {
    console.log(archive.pointer() + ' total bytes');
    console.log('archiver has been finalized and the output file descriptor has closed.');
});

archive.pipe(fileOutput);
archive.directory('dist/', false);
archive.on('error', function(err){
    throw err;
});
archive.finalize();

Sending the file is also very simple and done quickly:

// code/send.js

const request = require("request");
const fs = require("fs");
const path = require("path");
var options = {
    url: 'https://biehler-josef.de/upload.php',
    headers: {
        secret: process.env.JB_UPLOAD_SECRET
    }
}
var r = request.post(options, function optionalCallback (err, httpResponse, body) {
  console.log('Server responded with:', body, err);
})
var form = r.form()
form.append('zip-file', fs.createReadStream(path.join(__dirname, "..", 'test.zip')))

Summary

I replaced the FTP deployment with a HTTP upload endpoint. The /dist directory is zipped and unzipped with php. This was required because FTP upload does not work with travis very well.


Found a typo?

As I am not a native English speaker, it is very likely that you will find an error. In this case, feel free to create a pull request here: https://github.com/gabbersepp/dev.to-posts . Also please open a PR for all other kind of errors.

Do not worry about merge conflicts. I will resolve them on my own.

💖 💪 🙅 🚩
gabbersepp
Josef Biehler

Posted on January 25, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related