その場でzipフォルダーを作成しようとしています。zip には、Amazon S3 でホストされているライブラリからユーザーが選択した画像が保持されます。以下は私がこれまでに持っているコードです。
投稿から URL をリクエスト
function download_multi() {
//$user_id, $files, $project_id, $project_name
$this->load->library('aws');
$user = User::get_user();
$requestedHashes = $this->input->post("files");
$files = array();
foreach($requestedHashes as $hash) {
$files[] = hex_to_string($hash);
}
$project_id = $this->input->post("projectid");
$project = new Project($project_id);
$project_name = $project->project_name;
$this->aws->create_zip($user->id, $files, $project_id, $project_name, (int)$this->input->post("downloadToken"));
}
郵便番号を作成
public function create_zip($user_id, $files, $project_id, $project_name, $cookie) {
//create a random folder name to avoid collision.
$this->folder = md5(time() . rand());
if(!mkdir('./files' . '/' . $this->folder, 0777, TRUE)) {
exit("Folder not created\n");
}
//create zipfile
$this->filename = $this->local_file_path . $this->folder . '/files.zip';
$zip = new ZipArchive();
if ($zip->open($this->filename, ZIPARCHIVE::CREATE) !== TRUE) {
exit("cannot open <$this->filename>\n");
}
//create options for downloading each file to the server
//temporarily to add to archive
$opt = array('preauth' => '+1 minutes');
//download each file to the server.
foreach ($files as $file) {
//generate a link.
$response = $this->s3->get_object($this->bucket, $this->_make_path($user_id, $project_id) . $file, $opt);
//get filename.
$file_name = explode('?', basename($response));
//add filename to array
$local_files[] = $file_name[0];
//copy the file from aws to local server.
if(copy($response, $this->local_file_path . $this->folder . '/' . $file_name[0])) {
$zip->addFile($this->local_file_path . $this->folder . '/' . $file_name[0], $file_name[0]);
}
}
//close zip
$zip->close();
//die(var_dump(file_exists($this->filename)));
//kill each temp file
/*foreach ($local_files as $file) {
unlink($this->local_file_path . $this->folder . '/' . $file);
}*/
//load download helper.
$this->ci->load->helper('download');
//download
stream_download("APP_{$project_name}_" . time() . ".zip", $this->filename, $cookie);
}
ダウンロードヘルパー
function stream_download($filename = '', $data = '', $cookie = NULL)
{
//die($cookie);
if ($filename == '' OR $data == '')
{
return FALSE;
}
// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if (FALSE === strpos($filename, '.'))
{
return FALSE;
}
// Grab the file extension
$x = explode('.', $filename);
$extension = end($x);
// Load the mime types
if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
}
elseif (is_file(APPPATH.'config/mimes.php'))
{
include(APPPATH.'config/mimes.php');
}
// Set a default mime if we can't find it
if ( ! isset($mimes[$extension]))
{
$mime = 'application/octet-stream';
}
else
{
$mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
}
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
{
header('Content-Type: "'.$mime.'"');
header('Set-Cookie: fileDownloadToken="'.$cookie.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".filesize($data));
}
else
{
header('Content-Type: "'.$mime.'"');
header('Set-Cookie: fileDownloadToken="'.$cookie.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".filesize($data));
}
flush();
}
ジャバスクリプト
downloadSelectedFiles: function(e) {
//window.XmlHttpRequest = new XmlHttpRequest();
console.log("Block UI");
var that = this;
var url = config.base + "projects/download_multi";
var projectId = $("li.selected").find('li.js-select-file').data('projectid');
var images = {};
images.hashes = [];
var token = new Date().getTime();
$("li.selected").each(function(i){
images.hashes.push($(this).find('li.js-select-file').data('filename'));
});
//window.location.href = url;
$.post(url, { files: images.hashes, projectid: projectId, downloadToken: token }, function(data){
var fileDownloadCheckTimer = window.setInterval(function() {
console.log("checking...");
var cookieValue = $.cookie('fileDownloadToken');
console.log(parseInt(cookieValue), parseInt(token));
if( parseInt(cookieValue) == parseInt(token) ) {
that.finishDownload()
} else {
console.log("Don't Match");
}
}, 1000);
/*var iframe = document.createElement("iframe");
iframe.src = config.base + data;
iframe.style.display = "none";
document.body.appendChild(iframe);
return false;*/
});
},
finishDownload: function() {
window.clearInterval(fileDownloadCheckTimer);
$.removeCookie('fileDownloadToken');
console.log("Unblock UI");
}
私が気づいたことの 1 つは、Cookie の値とトークンの一致を確認するときに、一方が文字列で、もう一方が int であるということです。私は自分の応答でヘッダーを取得するだけでなく、実際にダウンロードウィンドウを取得することもありません。