Codeigniter multiple file upload paths - file

I'm building an app which needs to take uploaded files and put them in separate directories for thumbnails and fullsize images. But $config['upload_path'] = './uploads/'; only allows me to select one upload path.
How do I define two or more upload paths?

Actually all you need to do is "re-initialize" the upload class. Codeigniter does not allow you to call the class twice with new parameters (it ignores the second request), however you can tell the class to manually load new parameters. Here are the basics: (notice the line "$this->upload->initialized($config)" This is the key.
// this is for form field 1 which is an image....
$config['upload_path'] = './uploads/path1';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '100';
$config['max_width'] = '1024';
$config['max_height'] = '768';
$this->upload->initialize($config);
$this->upload->do_upload($fieild_1);
// this is for form field 2 which is a pdf
$config['upload_path'] = './pdfs/path2';
$config['allowed_types'] = 'pdf';
$config['max_size'] = '300';
$this->upload->initialize($config);
$this->upload->do_upload($fieild_2);
I wrote an entire article about it here:
http://taggedzi.com/articles/display/multiple-file-uploads-using-codeigniter
You can change any of the allowed parameters in your second initialize script so that your second file can be of a completely different makeup. You can do this as many times as you like you just have to re-initialized for each file type. (You can even setup a config array and loop through if you like...)
Hope this helps.

You're conflating two issues here. You need to further decompose the problem into discrete tasks.
First of all, you need to set the appropriate upload directory. On my site, each user is directed to their own upload directory:
/images/member/1
/images/member/2
/images/member/3
My controller sets the upload directory dynamically, based on user id
$config['upload_path'] = "/images/member/$user_id";
Second, you need to process your uploaded file, creating resized and thumbnail images. My image processing library uses the same path that I passed to $config['upload_path'] as its root directory, and places its output into subdirectories relative to that dynamic root:
/images/member/1/resized
/images/member/1/thumbnails
My site is actually a little more complex than that. But the point is that setting $config['upload_path'] dynamically lets you have as many upload paths as you want.

The short (and disappointing) answer is: CodeIgniter's file uploading class was designed to accept 1 uploaded file per form.
The long answer is somewhere around here.

Related

Drupal upload then move doesn't update path or filename in file list

I have a custom form using a "managed_file" which uploads to temp folder. Programmatically, I then load that file and move it to its permanent storage (overwriting any existing file with the* name) e.g.
// Upload file
$upfile = $this->entityTypeManager->getStorage('file')->load($fid);
// Source and destination
$sourceUri = $this->fileSystem->realpath($upfile->getFileUri());
$destinationUri = $this->fileSystem->realpath(\Drupal::config('system.file')->get('default_scheme') . "://") . '/x/y/z/XYZ_NEW.pdf';
// Move and overwrite
$this->fileSystem->move($sourceUri, $destinationUri, FileSystemInterface::EXISTS_REPLACE);
All of this works (i.e. the file physically is moved into the correct place with correct name); however, the file displayed in the listings (i.e. /admin/content/files) still shows the incorrect temporary folder as the URI.
Basically the file in the listings page seems to be showing the original filepath and name* of a previously successfully moved* file.
If I load this file with incorrect URI, i.e. using the incorrect temp path, the data loads, but then will not have a file info (as it doesn't exist. Also clicking the filename by browser under listings will show page not found and the URL showing the old URL i.e. /system/temporary?file=XYZ.pdf).
If I load this file by correct URI, i.e. using the correct destination path, file not found - same if I go to the path directly in the browser.
It appears the managed file doesn't know it was moved. How to resolve this bug?
The docs for FileSystem::move say "Moves a file to a new location without database changes or hook invocation."
So you are going to need to update the file entity with the new values..
Try this, untested:
// Upload file
$upfile = $this->entityTypeManager->getStorage('file')->load($fid);
// Source and destination
$sourceUri = $this->fileSystem->realpath($upfile->getFileUri());
$destinationUri = $this->fileSystem->realpath(\Drupal::config('system.file')->get('default_scheme') . "://") . '/x/y/z/XYZ_NEW.pdf';
// Move and overwrite
$newFileName = $this->fileSystem->move($sourceUri, $destinationUri, FileSystemInterface::EXISTS_REPLACE);
// Set the new file path on the file entity.
$upfile->setFileUri($newFileName);
// Set the file to permanent if needed.
$upfile->setPermanent();
// Save entity with changes.
$upfile->save();
I did not test this though.
You can check the functions on the file entity in the docs here
It turns out the class based methods do not update the database
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21File%21FileSystem.php/function/FileSystem%3A%3Amove/8.9.x
The procedural version does
https://api.drupal.org/api/drupal/core%21modules%21file%21file.module/function/file_move/8.9.x

read/download file using local absolute path

I have one file which is stored at D:/home/abc.pdf locally.
I have to read this file using AngularJs
var path="D:/home/abc.pdf";
var doc = document.createElement("a");
doc.href = path;
doc.download = path;
doc.click();
window.URL.revokeObjectURL(path);
I am not able to download this file.Giving error like Failed-Network error
That is impossible since local files are protected. Else you would be able to manipulate the hard drive as you wanted just by running a local HTML page.
So : if you want to get a file from the computer's hard drive, you have to use an <input> field and ask the user to upload the file using it.

The file download folder view in Struts 2

I'm creating a project of a school. I want to show the uploaded stuff by teachers to students.
But I also need to save the file in the folder which is named as faculty name. Student will be able to browse the main directory and after that he can go in the particular faculties folder.
How can I do it? Any suggestions will be appreciated.
For file upload I would start with example like in this answer. Moving files from temporary folder could be easily done by the file uploading action.
For browsing files in your case I would create an action that is able to navigate to the folder where the files are and get a list of files from that folder. Something like this
String file = application.getRealPath("/upload");
File f = new File(file);
String [] fileNames = f.list();
File [] fileObjects= f.listFiles();
for (int i = 0; i < fileObjects.length; i++) {
if(!fileObjects[i].isDirectory()){
String fname = file+fileNames[i];
out.println(fileNames[i]);
}
}
Then map this files to the JSP as links. When that link is clicked you can retrieve the actual path on the server when action is executed. What to do with the data, of course you can return stream result from the action that is used for streaming to the client browser. You can use docs examples from the Struts site or like in this example.
To navigate to the folder use parameters in GET request, that will be used to store current directory in session. You can change it if a user change the current directory from the view layer.

Google Cloud Storage: download a file with a different name

I'm wondering if it's possible to download a file from Google Cloud Storage with a different name than the one that has in the bucket.
For example, in Google Cloud Storage I have stored a file named 123-file.txt but when I download it I would like choose a different name, let's say file.txt
I've noticed that the link for download it is like:
https://storage.cloud.google.com/bucket_name%2F123-file.txt?response-content-disposition=attachment;%20filename=123-file.txt
So I've tried to change it to:
https://storage.cloud.google.com/bucket_name%2F123-file.txt?response-content-disposition=attachment;%20filename=file.txt
But it still keeps downloading as 123-file.txt instead of file.txt
The response-content-disposition parameter can only be used by authorized requests. Anonymous links don't work with it. You have a few options:
The content-disposition of a particular object is part of its metadata and can be permanently set. If you always want a specific file to be downloaded with a specific name, you can just permanently set the content-disposition metadata for the object.
You can also generate signed URLs that include the response-content-disposition query parameter. Then the users will be making authorized requests to download the resource.
example (first option Brandon Yarbrough) with javascript library:
const storage = new Storage()
const fileBucket = storage.bucket('myBucket')
const file = fileBucket.file('MyOriginalFile.txt')
const newName = "NewName.txt"
await file.save(content, {
metadata: {
contentDisposition: `inline; filename="${newName}"`
}
})
the following is a part of a python script i've used to remove the forward slashes - added by google cloud buckets when to represent directories - from multiple objects, it's based on this blog post, please keep in mind the double quotes around the content position "file name"
def update_blob_download_name(bucket_name):
""" update the download name of blobs and remove
the path.
:returns: None
:rtype: None
"""
# Storage client, not added to the code for brevity
client = initialize_google_storage_client()
bucket = client.bucket(bucket_name)
for blob in bucket.list_blobs():
if "/" in blob.name:
remove_path = blob.name[blob.name.rfind("/") + 1:] # rfind gives that last occurence of the char
ext = pathlib.Path(remove_path).suffix
remove_id = remove_path[:remove_path.rfind("_id_")]
new_name = remove_id + ext
blob.content_disposition = f'attachment; filename="{new_name}"'
blob.patch()

How to create file in current system from within Grails controller action and save data fetched from database?

In my Grails application I need to create a file in current system in which I need to save information fetched from table in database. How to do this from within controller action? I don't have any idea of it.
I have created file as
File file=new File("file name.txt")
file.createNewFile();
then I have wrote values of MySQL database table fields in it as:
file<<patient.id
file<<patient.name
.
.
.
it stores data like continuous text but I want to have a .doc file in which data should get stored in table. I found Apache's POI for creating doc file but I am not getting how it works and how I should use it.
Not sure exactly what you want to store in a file but below is an example of how to easly write a String to a file using Apache-commons-io Which should be included in grails
import org.apache.commons.io.FileUtils;
class SomeController{
def writeToFile = {
def data = getSomeStringData();
def fileStore = new File("./path/to/files/ControllerOutput_${new Date()}.txt");
fileStore.createNewFile();
FileUtils.writeStringToFile(fileStore, data);
println("your file was created # {fileStore.absolutePath} and is ${fileStore.length()} bytes");
}
}
Does this help? If not, you need to explain exactly what your looking for.
This is a comment to Michael's answer (unfortunately I still don't have the reputation to reply on answers).
If you're struggling around the problem how to specifiy the relative path from within your controller's context, this might help you:
So if you have following folder you want to read/write files from/into"..
/myproject/web-app/temp/
you can access the file like this:
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
// getResource references to the web-app folder as root folder
Resource resource = AH.getApplication().getParentContext().getResource("/temp/myfile.txt)

Resources