Hello i'm testing on a new wordpress multi-site where i want to serve media files from an external object storage as cdn.
what i did:
mounted the external object storage (s3 compatible) with Goofys inside wp-content/uploads
I made this filter i my custom plugin:
function new_upload_dir($args) {
$cdn = 'https://cdn.domain.com';
$site= get_blog_details()->blog_id;
if($site == 1) {
$args['baseurl'] = $cdn;
} else {
$args['baseurl'] = $cdn . "/sites/" .$site;
}
$args['url'] = $args['baseurl'] . $args['subdir'];
return $args;
}
add_filter('upload_dir', 'new_upload_dir');
All the images are served over cdn.domain.com pointing to the s3 bucket, and uploads works well too. But now i noticed that some plugins also store some files in the upload dir for every subdomain site like the matomo plugin:
I need to know if there is a system in wordpress to specify different upload dirs, one for media files, one for plugins files, example wp-content/uploads-media and wp-content/uploads-plugins.
Thank you very much
Related
I am attempting to write a plugin that, upon activation, programmatically does everything that is needed to upload an image to the uploads directory. In other words: it does everything that would happen if you manually did the drag-and-drop of the image on the Add New Media Library Screen:
Details:
I am not submitting a POST request. I am simply trying to find out what functions I need to call in order to do the following (which wordpress does in the drag-and-drop Media Library screen:
Find and grab the image specified by the FULL path (example: image is located on the desktop. It is NOT in the uploads directory).
Upload that image, as well as various versions of that image, in the uploads directory
create a post of post_type equal to attachment
create relevant postmeta records
Example:
It seems like wp_insert_attachment simply cannot do this because the image MUST already exist in the uploads directory.
# Below is a comment from the wp_insert_attachment example:
// $filename should be the path to a file in the upload directory
This post just says this isn't possible with wp_insert_attachment but does not provide a solution.
Question(s):
How can I programmatically upload an attachment whose path does not exist in the wp-content/uploads directory? Instead, for example: the full path to the image is located on the desktop.
Is this simply impossible to do without doing it in the context of uploading the image via a form and POST request? Ideally I want to call some function that says "Here is the full path to the image which is located on the desktop. Now: do all the work necessary to upload the image within the context of my wordpress project."
Thanks!
I saw you were referencing your server's desktop. Make sure that the files you are trying to load are accessible by the WordPress App User!
If you have to do this programmatically, it looks like media_handle_sideload might do the trick. Same functionality as media_handle_upload, but I don't think it requires the POST request to activate it like media_handle_upload does.
So
Step 1: Move files to location accessible by the WordPress application (like wp-content/uploads)
Step 2: grab url for the file you need to "upload" (something like host/wp-content/uploads/image.jpg)
Step 3: Figure out the post Id you need to reference for the image, and use media_handle_sideload to validate and store the file (code snippet below from the Wordpress Codex)
<?php
// Need to require these files
if ( !function_exists('media_handle_upload') ) {
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
}
$url = "http://s.wordpress.org/style/images/wp3-logo.png";
$tmp = download_url( $url );
if( is_wp_error( $tmp ) ){
// download failed, handle error
}
$post_id = 0;
$desc = "The WordPress Logo";
$file_array = array();
// Set variables for storage
// fix file filename for query strings
preg_match('/[^\?]+\.(jpg|jpe|jpeg|gif|png)/i', $url, $matches);
$file_array['name'] = basename($matches[0]);
$file_array['tmp_name'] = $tmp;
// If error storing temporarily, unlink
if ( is_wp_error( $tmp ) ) {
#unlink($file_array['tmp_name']);
$file_array['tmp_name'] = '';
}
// do the validation and storage stuff
$id = media_handle_sideload( $file_array, $post_id, $desc );
// If error storing permanently, unlink
if ( is_wp_error($id) ) {
#unlink($file_array['tmp_name']);
return $id;
}
$src = wp_get_attachment_url( $id );
?>
If you have the file already on the server, but it doesn't have a path setup in wordpress yet (i.e. you can't browse to it from a web browser), there's a plugin called "Add from Server" where it opens a miniature file browser window that's connected to your server, and then it creates the database records in your WordPress instance to the files residing on the server, so that you can pull them up in the media browser on wp-admin.
Warning though, this plugin is a security risk since the plugin essentially gains file-access to your webserver's directory. If you have to, say, bulk upload a bunch of files to WordPress and they're already on the server, I would install the plugin, create the database records for the files, and then immediately deactivate and uninstall the plugin!
You are looking for media_handle_upload. You can then use wp_update_attachment_metadata.
Here is a basic version:
<?php
// Use 0 as your post ID if you don't want to attach it to any post
$image = media_handle_upload($file, $post_id);
wp_update_attachment_metadata( $image, $data );
?>
You can see a more advanced version using a frontend form here.
You could alternatively use media_handle_sideload if uploading an image from a URL.
We have a CPT which is used to manage various assets including image, pdf, CAD and other files.
Our client would like to keep these asset files seperate from their other media files and does NOT want them to appear in the WP media panel.
We have found this useful snippet which allows us to upload to a custom folder inside the WP uploads folder:
function my_upload_dir($upload) {
$upload['subdir'] = '/assets';
$upload['path'] = $upload['basedir'] . $upload['subdir'];
$upload['url'] = $upload['baseurl'] . $upload['subdir'];
return $upload;
}
add_filter('upload_dir', 'my_upload_dir');
$uploaded_file = wp_handle_upload($_FILES['xxxx'], $upload_overrides);
remove_filter('upload_dir', 'my_upload_dir');
How could we adapt this properly to upload images for this CPT to a custom 'assets' folder, for example: wp-content/assets ?
Thanks in advance for any help!
I'm setting up a site in Silverstripe 3 and have come up with a weird issue around uploading KMZ/KML files into the CMS.
The end goal is to allow CMS users to upload multiple KMZ/KML/GPX files to a page. These files will then be displayed as routes on a Google Map.
This is the has_many declaration:
static $has_many = array(
'RouteFiles' => 'File'
);
This is the getCMSFields code:
$routeFilesField = new UploadField('Route Files', 'Upload GPX/KMZ/KML files for your proposed route.', $this->RouteFiles());
$routeFilesField->getValidator()->allowedExtensions = array('kmz', 'kml', 'gpx');
$fields->addFieldToTab('Root.Map', $routeFilesField);
I have added the extensions to the FilesMatch section of the /assets/.htaccess file.
When I upload a KMZ or KML file to the CMS I get the following message in the Upload Field:
File information not found
What else do I need to do to make this work?
Adding the following to my _config.php has worked for me:
File::$allowed_extensions[] = 'kmz';
File::$allowed_extensions[] = 'kml';
File::$allowed_extensions[] = 'gpx';
I did not have to do anything else to allow these files types. The upload field worked and linking to the file on the front end worked.
this message means the upload to the temporary upload folder failed. you should check for the folder being writable or change it, see http://www.php.net/manual/en/ini.core.php#ini.upload-tmp-dir
I am creating a website that will allow users to upload projects. Project submissions will consist of .zip file. Once the user uploads their project, I need to unzip the .zip file and find the .html file . Also, it needs to be possible to upload these projects through the web interface "Add New Content" and through Node.create by way of the services module.
note I'm using the PclZip library.
This is part of the code I use when the uploaded file but it does not extract the file
function custom_unzip_node_submit($node, $form, &$form_state) {
if ($node->type == 'flipper') {
$p_zipname = base_path() .'sites/default/files'.$form_state["complete form"]["#node"]->field_file["und"][0]["filename"];
$to_extract = base_path() . 'test/';
$zip = new PclZip($p_zipname);
$ar = $zip->extract(PCLZIP_OPT_PATH, $to_extract);
}}
I have been assigned a new task by a client, a document sharing application to be made using the MVC design pattern. Here are the requirements:
Uploads and downloads files with a browser
Store the document in db if that are more secure documents else store on the directory with options of password enabled or accessible without password
Every user will be have own document catalog / workspace from where he can be able to share documents with other users as well. and public shared area to share and upload files
Super admin will be able monitor the file upload logging for monitoring purpose.
I have rough idea but I would really like to know your thoughts about above points especially what is in bold up there.
The third point above is most important and I am not sure where to start from and how to go about logging the uploads.
I am basically asking for implementation details about the third and fourth points.
Here is how I implement this with CakePHP and it works nicely. First, I make sure my app code sits above the public html directory so that it is not exposed to the web. So basically, the only files the users have direct access to is the index.php file, the css/js and image files.
Then, I update my file management model to save and delete files on the fly:
function beforeSave() {
extract($this->data['Upload']['file']);
if(isset($name) and !empty($name)) {
$filename = time().'-'.$name;
if ($size && !$error) {
move_uploaded_file($tmp_name, APP . 'media/files/' . $filename);
$this->data['Upload']['file'] = $filename;
$this->data['Upload']['name'] = $name;
$this->data['Upload']['file_type'] = $type;
}
} else {
// remove the photo so it is not updated
unset($this->data['Upload']['file']);
}
return parent::beforeSave();
}
function beforeDelete() {
$data = $this->read(null, $this->id);
if( is_file( APP . 'media/files/' . $data['Upload']['file'])) {
unlink(APP . 'media/files/' . $data['Upload']['file']);
}
return true;
}
This will manage the file upload and put all of the naming information into the database. And since the app/media/files directory is not accessible to the web, I do not have to protect the directory. It means that no matter what file the user wants, they have to access it from the website.
Then, all you have to do is make sure the model table has a "shareable" flag for the user to indicate that the file is accessible to the world, and then anyone can see the file and download it.