How to create a new directory in grails applicatio

2019-09-04 14:48发布

问题:

I want to create a new directory to store all pdf reports generated by jasper reports and they should be accessible to users to download as well

For example: I am exporting the a file called "pdfreport20110804788.pdf".when i put this file in that directory .i set certain things in controller method and i need the file created to be returned from the groovy method where the new directory is created and its is exported as pdf file so that file should be returned to the controller calling method for further operations

response.setContentType("application/octet-stream")
response.setHeader("Content-disposition", "attachment;filename=${file.getName()}")
response.outputStream << file.newInputStream()

So ,i have been trying these thing by creating the file using the createTempFile method and returning the file to the controller but the file was getting downloaded to c:\ ... location without asking to download or open .can any one please give me the solution for this

回答1:

There are two things you need to be aware of:

1.) Files generated on the server's disk cannot be directly accessed by a user on your web site. You have to deliver the files through the browser via an output stream.

2.) You cannot freely access the disk of a user on your web site. So, if your web site creates a file on "c:\website\file.pdf" it will always go to the server's "c:" drive and never to the end users "c:" drive. Remember the "c:\" drive is mostly a Windows thing so Unix or mobile users would NOT be able to use the site even if you could do this because they don't have a "c:" drive.

so, here is what i would do if you want to store the files and allow the user to download them now or later (not tested and it could be better but shows the concept)...

create a class that represents your directory of reports

class ReportDirectory{

   static final String path = "./path/to/reports/"; //<-- generic path on your SERVER!

   static{
       //static initializer to make sure directory gets created.  Better ways to do this but this will work!

       File pathAsFile = new File(path).mkdirs()

       if (pathAsFile.exists()){
          println("CREATED REPORT DIRECTORY @ ${pathAsFile.absolutePath}");
       }else{
          println("FAILED TO CREATE REPORT DIRECTORY @ ${pathAsFile.absolutePath}");
       }

   }

   public static File[] listFiles(){
       return new File(path).listFiles(); //<-- maybe use filters to just pull pdfs?
   }

   public static void addFile(File file){
       FilesUtil.copyFileToDirectory(file, new File(path)); //<-- using apache-commons-io
   }

   public static void deleteAll(){
       listFiles().each(){ fileToDelete ->
           fileToDelete.delete();
       }
   }

   public static File findFile(String name){
       listFiles().each(){ fileToCheck ->

           if (fileToCheck.name.equals(name)){
               return fileToCheck
           }
       }
       return null
   }

}

Then in your controller you could do things like this....

class ReportController{

   def runReport = {
       File report = createReport() //<-- your method to create a report.
       ReportDirectory.addFile(report);

       redirect(action:"downloadFle" params:[fileName:report.name])

   }    


   def showAllFiles = {
       [files:ReportDirectory.listFiles()]
   }

   def downloadFile = {
      def fileName = params.fileName;

      def fileToDownload = ReportDirectory.findFile(fileName);

      if (fileToDownload){

      response.setContentType("application/octet-stream")
      response.setHeader("Content-disposition", "attachment;filename=${fileToDownload .getName()}")
      response.outputStream << fileToDownload.newInputStream()  //<-- ask the user to download
     }else{
         //handle when the file is not found
     }

   }

   def deleteAllFiles ={
       ReportDirectory.deleteAllFiles()

       [files:ReportDirectory.listFiles()] //<-- return the remaining files, if any.
   }


}

A few comments about this solution...

-this doesn't address MIME types so the browser won't be able to figure out what kind of binary data is coming over the wire.

is this helpful?