Hi,

> I wouldn't say that. File transfers are affected by IO, not CPU.
I've read this somewhere several months ago and yesterday again here:
https://blogs.warwick.ac.uk/chrismay/entry/mod_x_sendfile/

> I'd like to see how you implemented it.
Basically like the HowTo
[https://wiki.apache.org/tapestry/Tapestry5HowToStreamAnExistingBinaryFile]
but I shortened it a little bit:

AttachmentStreamResponse.java:
    public class AttachmentStreamResponse implements StreamResponse {

        private InputStream inputStream = null;
        private String contentType = "text/plain";
        private FileReference fileReference;

        public AttachmentStreamResponse(FileReference fileReference)
throws FileNotFoundException {
            this.fileReference = fileReference;
            this.inputStream = new BufferedInputStream(new
FileInputStream(fileReference.getAbsolutePath()));
        }

        [getter for contentType and inputStream]

        @Override
        public void prepareResponse(Response response) {
            response.setHeader("Content-Disposition", "attachment;
filename=\"" + fileReference.getFileName() + "\"");
            response.setContentLength((int) fileReference.getSizeInBytes());
            response.setHeader("Expires", "0");
            response.setHeader("Cache-Control", "must-revalidate,
post-check=0, pre-check=0");
            response.setHeader("Pragma", "public");
        }
    }

And in the Component, where the Actionlink points to:
    private StreamResponse onActionFromDownload(long fileReferenceId,
String folderName) throws IOException {
        FileReference fileToSend = new FileReference(fileReferenceId);

        if (folderName != null
                && [... is file existing and allowed to download? ...]) {
            return new AttachmentStreamResponse(fileToSend);
        }
       
        return null;
    }

The only ugly thing for users who want to copy the direct file link was
the event request:
[server]/index.ajaxuploadarea.download/61/nEWEaMExZ5xbJzSmNQQe?t:ac=5tAnW,
where 61 is the fileReferenceId and nEW.. the folderName.
I've now also integrated url rewriting (as
http://blog.tapestry5.de/index.php/2010/09/06/new-url-rewriting-api/).

This took the most time :-D

public class FileDownloadLinkTransformer implements
ComponentEventLinkTransformer {

    private enum ManuallyTransformedRequest {
        FILE_DOWNLOAD, NOT_MANUALLY_TRANSFORMED;
    }
    private final String FILE_DOWNLOAD_COMPONENT_PATH = "/" +
Index.class.getSimpleName().toLowerCase() + ".ajaxuploadarea.download";
    private final String FILE_DOWNLOAD_COMPONENT_PATH_REGEX = "/" +
Index.class.getSimpleName().toLowerCase() +
"\\.ajaxuploadarea\\.download.*";
    private final String FILE_DOWNLOAD_COMPONENT_PATH_TRANSFORMATION =
"/download";
    private final String ACTIVATION_CONTEXT_PARAMETER_NAME = "t:ac";
    @Inject
    private TypeCoercer typeCoercer;

    @Override
    public Link transformComponentEventLink(Link defaultLink,
ComponentEventRequestParameters parameters) {
        switch (getTypeOfPage(defaultLink)) {
            case FILE_DOWNLOAD:
                String context = exctractFileIdAndFolderName(defaultLink);
                if (context != null) {
                   
defaultLink.removeParameter(ACTIVATION_CONTEXT_PARAMETER_NAME);
                    return
defaultLink.copyWithBasePath(getDevelopeModeExtension() +
FILE_DOWNLOAD_COMPONENT_PATH_TRANSFORMATION + context);
                }
                break;
            case NOT_MANUALLY_TRANSFORMED:
                break;
        }

        return defaultLink;
    }

    @Override
    public ComponentEventRequestParameters
decodeComponentEventRequest(Request request) {
        String requestedPath = request.getPath();
        if
(requestedPath.startsWith(FILE_DOWNLOAD_COMPONENT_PATH_TRANSFORMATION)) {
            return new ComponentEventRequestParameters(
                    Index.class.getSimpleName(),
                    Index.class.getSimpleName(),
                    FILE_DOWNLOAD_COMPONENT_PATH.replaceFirst("/" +
Index.class.getSimpleName().toLowerCase() + "\\.", ""),
                    EventConstants.ACTION,
                    new EmptyEventContext(),
                   
toEventContext(requestedPath.substring(FILE_DOWNLOAD_COMPONENT_PATH_TRANSFORMATION.length()
+ 1)));
        }
        return null;
    }

    private ManuallyTransformedRequest getTypeOfPage(Link link) {
        if (link.getBasePath().matches(getDevelopeModeExtension() +
FILE_DOWNLOAD_COMPONENT_PATH_REGEX)) {
            return ManuallyTransformedRequest.FILE_DOWNLOAD;
        }
        return ManuallyTransformedRequest.NOT_MANUALLY_TRANSFORMED;
    }

    private String exctractFileIdAndFolderName(Link link) {
        if (link.getBasePath().matches(getDevelopeModeExtension() +
FILE_DOWNLOAD_COMPONENT_PATH + "/[0-9]+/[0-9a-zA-Z].+")) {
            return
link.getBasePath().substring((getDevelopeModeExtension() +
FILE_DOWNLOAD_COMPONENT_PATH).length());
        }
        return null;
    }

    private EventContext toEventContext(String value) {
        return value == null ? new EmptyEventContext() : new
ArrayEventContext(typeCoercer, (Object[]) value.split("/"));
    }

    private String getDevelopeModeExtension() {
        return PlainTraySetting.PRODUCTION_MODE ? "" : "/webapp";
    }
}

I know, it got a bit ugly, but at least it works and the most parts are
strongly typed.


René

On 24.01.2013 15:29, Thiago H de Paula Figueiredo wrote:
> On Thu, 24 Jan 2013 11:49:05 -0200, René Bernhardsgrütter
> <rene.bernhardsgruet...@gmail.com> wrote:
>
>> Hi Thiago,
>
> Hi!
>
>> thank you for your answer!
>
> ;)
>
>> I thought that Java/Tomcat wouldn't be optimal to handle large/many file
>> transfers in a web environment (too high cpu usage) and that Apache
>> would handle it better -- correct me, if I'm wrong.
>
> I wouldn't say that. File transfers are affected by IO, not CPU.
>
>> I've now implemented the StreamResponse solution you suggested and it
>> works fine.
>
> I'd like to see how you implemented it.
>
>> Anyway, I'll see if the performance will be a problem.
>
> That's exactly how you should do: instead of just guessing how it'll
> perform, implement and test. :)
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to