HTML Compress File Upload

File compression before upload on the client-side

Flash's inbuilt implementation of ByteArray has a method (ByteArray::deflate to deflate the contents (of the bytearray) The deflate algorithm is the DEFLATE Compressed Data Format Specification version 1.3.

There;s also a ByteArray::compress method which compresses using the zlib algorithm

Hold on a bit, I'll write you some sample code to use this class and expose it to JavaScript.

EDIT

I've uploaded the file at http://www.filefactory.com/file/cf8a39c/n/demo5.zip

EDIT 2 For those who couldn't download the files:

My ActionScript code in demo5.fla (compiled to demo5.swf)

import flash.external.ExternalInterface;
import flash.net.FileReference;
import flash.events.Event;
import flash.utils.ByteArray;

if(ExternalInterface.available) {
//flash.system.Security.allowDomain("localhost");
ExternalInterface.addCallback("deflate", doDeflate);
ExternalInterface.addCallback("compress", doCompress);
}

var method:String="deflate";
var b:ByteArray;
function doCompress(_data:String):void {
method="compress";
exec(_data);
}

function doDeflate(_data:String):void {
method="deflate";
exec(_data);
}

function exec(_data:String):void {
b=new ByteArray();
b.writeUTFBytes(_data);
b.position=0;
if(method=="compress") {
b.compress();
} else if(method=="deflate") {
b.deflate();
}
executed();
}

function executed():void {
if(ExternalInterface.available) {
b.position=0;
var str:String=b.readUTFBytes(b.bytesAvailable);
ExternalInterface.call("onExec", str);
}
}

My HTML code to embed the swf:

<button onclick="doDeflate()">Deflate</button>
<button onclick="doCompress()">Compress</button>
<div id="flashContent">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="1" height="1" id="demo5" align="middle">
<param name="movie" value="demo5.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="play" value="true" />
<param name="loop" value="true" />
<param name="wmode" value="window" />
<param name="scale" value="showall" />
<param name="menu" value="true" />
<param name="devicefont" value="false" />
<param name="salign" value="" />
<param name="allowScriptAccess" value="always" />

<embed src="demo5.swf" quality="high" bgcolor="#869ca7"
width="1" height="1" name="demo5" align="middle"
play="true" loop="false" quality="high" allowScriptAccess="always"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer">
</embed>
</object>
</div>

and finally the javascript code:

function doDeflate() {
var data="fdg fhnkl,hgltrebdkjlgyu ia43uwriu67ri8m nirugklhvjsd fgvu";
//DATA CONTAINS DATA TO BE DEFLATED
thisMovie("demo5").deflate(data);
}

function doCompress() {
var data="fdg fhnkl,hgltrebdkjlgyu ia43uwriu67ri8m nirugklhvjsd fgvu";
//DATA CONTAINS DATA TO BE DEFLATED
thisMovie("demo5").compress(data);
}

function onExec(data) {
//DATA CONTAINS THE DEFLATED DATA
alert(data);
}

function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}

HTML Compress File Upload?

Not using pure HTTP. You could do it using silverlight or flash, though.

Upload compressed image file from client-side using JavaScript

  1. You can only change a file input value with another list
    here is how: https://stackoverflow.com/a/52079109/1008999 (also in the example)
  2. Using the FileReader is a waste of time, CPU, Encoding & decoding and RAM...
    use URL.createObjectURL instead
  3. Don't use canvas.toDataURL... use canvas.toBlob instead
  4. Canvas have bad compression, read earlier comment and see the jsfiddle proff...
    If you insist on using canvas to try and squeeze the size down then
    1. First try to see if the image is in a reasonable size first
    2. Compare if the pre existing image file.size is smaller than what the canvas.toBlob provides and choose if you want the old or the new one instead.
    3. If resizing the image isn't enough have a look at this solution that change the quality until a desired file size & image aspect have been meet.

Without any testing, this is how i would have refactor your code too:

/**
* @params {File[]} files Array of files to add to the FileList
* @return {FileList}
*/
function fileListItems (files) {
var b = new ClipboardEvent('').clipboardData || new DataTransfer()
for (var i = 0, len = files.length; i<len; i++) b.items.add(files[i])
return b.files
}

// Takes upload element id ("file1") and a maxSize to resize, ideally on a change event
window.resizePhotos = async function resizePhotos (input, maxSize) {
const file = input.files

if (!file || !file.type.match(/image.*/)) return

const image = new Image()
const canvas = document.createElement('canvas')
const max_size = maxSize
image.src = URL.createObjectURL(file)
await image.decode()
let width = image.width
let height = image.height

// Resizing the image and keeping its aspect ratio
if (width > height) {
if (width > max_size) {
height *= max_size / width
width = max_size
}
} else {
if (height > max_size) {
width *= max_size / height
height = max_size
}
}
canvas.width = width
canvas.height = height
canvas.getContext('2d').drawImage(image, 0, 0, width, height)
const resizedImage = await new Promise(rs => canvas.toBlob(rs, 'image/jpeg', 1))

// PS: You might have to disable the event listener as this might case a change event
// and triggering this function over and over in a loop otherwise

input.files = fileListItems([
new File([resizedImage], file.name, { type: resizedImage.type })
])
}

jQuery($ => {
// Resets the value to when navigating away from the page and choosing to upload the same file (extra feature)
$('#file1').on('click touchstart' , function(){
$(this).val('')
})

// Action triggers when user has selected any file
$('#file1').change(function(e) {
resizePhotos(this, 1024)
})
})

Can a large file be compressed before upload from UI in angular?

How about using html-to-image plugin to convert image to lower quality and then apply upload as you are doing.

npm install --save html-to-image

You can try other htmlToImage method, up to you. What I have used is below:

htmlToImage.toJpeg(node, { quality: 0.95 }).then(function (dataUrl) {
let link = document.createElement('a');
link.download = "page" + '.jpeg';
link.classList.add("specialanchor")
link.href = dataUrl;
link.click();
}).catch(function (error) {
// console.error('oops, something went wrong!', error);
});

To learn more:
https://www.npmjs.com/package/html-to-image

Compress files (client side) and upload

There is no built-in functionality to achieve this...

But you can do this using FileReader API and javascript zip implementation like this one http://stuk.github.io/jszip/

compress selected video file before upload in javascript

An mp4 file is a container which will have video and audio tracks in it - these tracks will typically already be compressed by the encoder depending on which codec is used, h.264 for example.

If you want to further compress or re-encode the video it is possible, for example using a browser based ffmpeg solution, but even though these solutions may leverage the latest web assembly language technology this will not be quick and may not give you either the compression or quality you are looking for.

You can see some example here to experiment with: https://github.com/ffmpegwasm/ffmpeg.wasm

Compress file before upload via http

Browsers never compress uploaded data because they have no way of knowing whether the server supports it.

Downloaded content can be compressed because the Accept-Encoding request header allows the browser to indicate to the server that it supports compressed content. Unfortunately, there's no equivalent protocol that works the other way and allows the server to indicate to the browser that it supports compression.

If you have control over the server and client (e.g. using silverlight, flash) then you could make use of compressed request bodies.



Related Topics



Leave a reply



Submit