cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - New to the community? Learn how to post a question and get help from PTC and industry experts! X

Best way to download files from Windchill Server to client

MV_10441462
10-Marble

Best way to download files from Windchill Server to client

I'm looking to download a zip from my windchill server(temp location) to the client machine.

The zip was actually created as a result of an custom action.

So basically, when I click on the action a zip should get downloaded, that's my requirement.

Please suggest me your ideas or share me any existing solution.

Many thanks in advance.

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @MV_10441462 

depends how do you start your function. 

usually you get request and get the outputstream from it and flush (send) the data to the client as @avillanueva's example shows you. . 

 

here is short snip with a zipStream but you need to learn how to add files to the zip stream

 

 

HTTPResponse resp; // you need to get respons from commandBean or whereever HttpServletResponse response = nmCommandBean.getResponse(); 

ByteArrayOutputStream zipOut = new ByteArrayOutputStream();
CheckedOutputStream checksum = new CheckedOutputStream(zipOut, new Adler32());
ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(checksum));

InputStream contentStream = ContentServerHelper.service.findContentStream(appDatatToZip);
		// definice filename s cestou v zip
String fileZipEntry = appDatatToZip.getFileName();
addStreamToZip(fileZipEntry, zipOutputStream, contentStream); // annother sub method where the content is writen to zip

zipOutputStream.close();
		
OutputStream output = resp.getOutputStream();

resp.setHeader("Content-disposition", "attachment; filename=zipDownloadFile.zip");
resp.setHeader("Content-Type", "application/zip");

output.write(zipOut.toByteArray()); // zip stream written to the respons outputStream

output.flush();
output.close();

 

 

 

PetrH

View solution in original post

10 REPLIES 10

I did this with a JSP tied to that custom action:

BOMExportExcelUtility excelUtil=BOMExportExcelUtilityImpl.createBOMExportExcelUtility();
                    //7. Sub-module create Excel File for user download
                    response.reset();
                    excelUtil.createExcelFile(response.getOutputStream(),sheet1,sheet2);
                    ServletOutputStream outs = response.getOutputStream();
                    response.setHeader("Content-type","application/ms-excel");
                    String version=VersionControlHelper.getVersionIdentifier((Versioned)bom).getValue();
                    if (version.indexOf('.')!=-1)
                        version=version.substring(0, version.indexOf('.')); //just get first part
                    
                    String filename=bom.getNumber()+version;
                    response.setHeader("Content-disposition","attachment; filename="+filename+".XLS");//should prompt for download
                    
                    excelUtil.writeFile();
                    //8. Return response to user's browser session.
                    outs.flush();
                    outs.close();

This is the section where my code creates an XLS file and streams it back to the client. User downloads the file.

Hi @MV_10441462 

example  from @avillanueva is very good one how to download file.

I would add that you need to write own sollution. 

 

Create zip in java

Collect files from Windchill  

Add files to the zip

push the zip stream to the client user

 

PetrH

Hi @HelesicPetr 

 

Can you please help me with the snippet to push the zip stream to client user?

 

Hi @MV_10441462 

depends how do you start your function. 

usually you get request and get the outputstream from it and flush (send) the data to the client as @avillanueva's example shows you. . 

 

here is short snip with a zipStream but you need to learn how to add files to the zip stream

 

 

HTTPResponse resp; // you need to get respons from commandBean or whereever HttpServletResponse response = nmCommandBean.getResponse(); 

ByteArrayOutputStream zipOut = new ByteArrayOutputStream();
CheckedOutputStream checksum = new CheckedOutputStream(zipOut, new Adler32());
ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(checksum));

InputStream contentStream = ContentServerHelper.service.findContentStream(appDatatToZip);
		// definice filename s cestou v zip
String fileZipEntry = appDatatToZip.getFileName();
addStreamToZip(fileZipEntry, zipOutputStream, contentStream); // annother sub method where the content is writen to zip

zipOutputStream.close();
		
OutputStream output = resp.getOutputStream();

resp.setHeader("Content-disposition", "attachment; filename=zipDownloadFile.zip");
resp.setHeader("Content-Type", "application/zip");

output.write(zipOut.toByteArray()); // zip stream written to the respons outputStream

output.flush();
output.close();

 

 

 

PetrH

mprotas
5-Regular Member
(To:HelesicPetr)

@HelesicPetr- how can I overwrite the HttpServletResponse from NmCommandBean::getResponse() when whenever I try to use this method I retrieve IllegalStateException - Already using writer?

I want to perform downloading .zip file generated on the server-side from Wizard's FormProcessor. Is there any solution for that? Here is my example code of custom FormProcessor:

 

private ExportPackageFileManager fileManager;

    @Override
    public FormResult doOperation(NmCommandBean nmCommandBean, List<ObjectBean> list) throws WTException {
        FormResult result = super.doOperation(nmCommandBean, list);
        WTPart contextPart = (WTPart) WizardUtils.getContextObject(nmCommandBean);
        setFileManager(contextPart);

        HttpServletResponse response = nmCommandBean.getResponse();
        Path path = fileManager.getZipFilePath();
        String fileName = path.getFileName().toString();

        response.reset();
        try(ServletOutputStream outputStream = response.getOutputStream()) {
            response.setStatus(200);
            response.setHeader("X-Content-Type-Options", null);
            response.setHeader("Content-Type", "application/zip");
            response.setHeader("Content-disposition", "attachment; filename=" + fileName);
            response.setContentLength((int) path.toFile().length());
            Files.copy(path, outputStream);
            result.addDynamicRefreshInfo(new DynamicRefreshInfo(contextPart, contextPart, DynamicRefreshInfo.Action.UPDATE));
            return result;
        } catch (IOException | IllegalStateException e) {
            throw new WTException("Could not send file!");
        }
    }

 

 Whole logic for fetching files, zipping them works just fine. Whenever I click "Submit" button on my Wizard - window freezes and won't close automatically.

 

response.reset() is being used to avoid getting IllegalStateException but on the other hand it causes the window to freeze.

 

Thanks in advance.

HI @mprotas 

Why do you use the file.copy?

try to use the output.write() with transferred file to the byte.

 

PetrH

mprotas
5-Regular Member
(To:HelesicPetr)

Hi @HelesicPetr,

Changing from Files.copy() to more extensive writing to OutputStream object do not change anything in the freezing of Wizard's window after performing download of .zip file.

It looks like this:

 

Here is the current version of code:

 

@Override
    public FormResult doOperation(NmCommandBean nmCommandBean, List<ObjectBean> list) throws WTException {
        FormResult result = super.doOperation(nmCommandBean, list);
        WTPart contextPart = (WTPart) WizardUtils.getContextObject(nmCommandBean);
        setFileManager(contextPart);

        HttpServletResponseWrapper response =  new HttpServletResponseWrapper(nmCommandBean.getResponse());
        Path path = fileManager.getZipFilePath();
        String fileName = path.getFileName().toString();

        response.reset();
        try(ServletOutputStream outputStream = response.getOutputStream()) {
            response.setStatus(200);
            response.setHeader("X-Content-Type-Options", null);
            response.setHeader("Content-Type", "application/zip");
            response.setHeader("Content-disposition", "attachment; filename=" + fileName);
            response.setContentLength((int) path.toFile().length());
            //Files.copy(path, outputStream);
            File file = new File(fileManager.getZipFilePath().toString());
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try(FileInputStream fis = new FileInputStream(file)) {
                byte[] buf = new byte[1024];
                for (int readNum; (readNum = fis.read(buf)) != -1;) {
                    bos.write(buf, 0, readNum);
                }
            }
            catch (IOException e) {
                System.out.println("Test");
            }
            outputStream.write(bos.toByteArray());
            outputStream.flush();
            outputStream.close();
            result.addDynamicRefreshInfo(new DynamicRefreshInfo(contextPart, contextPart, DynamicRefreshInfo.Action.UPDATE));
            return result;
        } catch (IOException | IllegalStateException e) {
            throw new WTException("Could not send file!");
        }
    }

 

 

Hi @mprotas 

The point is that you can not use the reset method to reset the response.

If you use the reset, then you lost the connection to your wizard window.

Remove it.

You need to solve the IllegalStateException issue, and .reset method is not the solution. 

PetrH

mprotas
5-Regular Member
(To:HelesicPetr)

Yeah, but without this reset() method I receive that IllegalStateException mentioned above. Is there any workaround to perform downloading file from FormProcessor Wizard's window?

@mprotas 

Yes, the export mechanism used for downloading a WTDocument objects to a zip file.

 

PetrH

Top Tags