001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt.client.ui.input.upload.impl;
029
030import org.opencms.gwt.client.ui.input.upload.CmsFileInfo;
031import org.opencms.gwt.client.ui.input.upload.I_CmsUploadDialog;
032
033import com.google.gwt.core.client.JavaScriptObject;
034import com.google.gwt.core.client.JsArray;
035
036/**
037 * File API implementation of the file uploader.<p>
038 */
039public class CmsUploaderFileApi extends CmsUploaderFormData {
040
041    /**
042     * @see org.opencms.gwt.client.ui.input.upload.impl.CmsUploaderFormData#upload(java.lang.String, java.lang.String, boolean, java.lang.String, com.google.gwt.core.client.JsArray, com.google.gwt.core.client.JavaScriptObject, boolean, org.opencms.gwt.client.ui.input.upload.I_CmsUploadDialog)
043     */
044    @Override
045    protected native void upload(
046        String uploadUri,
047        String targetFolder,
048        boolean isRootPath,
049        String postCreateHandler,
050        JsArray<CmsFileInfo> filesToUpload,
051        JavaScriptObject filesToUnzip,
052        boolean keepFileNames,
053        I_CmsUploadDialog dialog) /*-{
054        var self = this;
055
056        function addPlainField(requestBody, fieldName, fieldValue) {
057            requestBody += "Content-Disposition: form-data; name=" + fieldName
058                    + "\r\n";
059            requestBody += "Content-Type: text/plain\r\n\r\n";
060            requestBody += fieldValue + "\r\n";
061            requestBody += "--" + boundary + "--";
062        }
063
064        // is executed when there was an error during reading the file
065        function errorHandler(evt) {
066            self.@org.opencms.gwt.client.ui.input.upload.impl.CmsUploaderFileApi::onBrowserError(Lorg/opencms/gwt/client/ui/input/upload/I_CmsUploadDialog;Ljava/lang/String;)(dialog,evt.target.error.code);
067        }
068
069        // is executed when the current file is read completely
070        function loaded(evt) {
071            // get the current file name/override-name and obtain the read file data
072            var fileName = file.overrideFileName ? file.overrideFileName
073                    : file.name ? file.name : file.fileName;
074            var fileData = evt.target.result;
075            if (fileData == null) {
076                fileData = "";
077            }
078            var fileInputName = "file_" + curIndex;
079            addPlainField(
080                    body,
081                    fileInputName
082                            + @org.opencms.gwt.shared.I_CmsUploadConstants::UPLOAD_FILENAME_ENCODED_SUFFIX,
083                    encodeURI(fileName));
084            body += "Content-Disposition: form-data; name=\"" + fileInputName
085                    + "\"; filename=\"" + encodeURI(fileName) + "\"\r\n";
086            body += "Content-Type: application/octet-stream\r\n\r\n";
087            body += fileData + "\r\n";
088            body += "--" + boundary + "\r\n";
089            // are there any more files?, continue reading the next file
090            if (filesToUpload.length > ++curIndex) {
091                file = filesToUpload[curIndex];
092                this.readAsBinaryString(file);
093            } else {
094                // there are no more files left append the infos to the request body
095                appendInfos();
096                // create the request and post it
097                var xhr = new XMLHttpRequest();
098                xhr.open("POST", uri, true);
099                // simulate a file MIME POST request.
100                xhr.setRequestHeader("Content-Type",
101                        "multipart/form-data; boundary=" + boundary);
102                xhr.overrideMimeType('text/plain; charset=x-user-defined');
103                xhr.onreadystatechange = function() {
104                    if (xhr.readyState == 4) {
105                        if (xhr.status == 200) {
106                            dialog.@org.opencms.gwt.client.ui.input.upload.I_CmsUploadDialog::parseResponse(Ljava/lang/String;)(xhr.responseText);
107                        } else if (xhr.status != 200) {
108                            dialog.@org.opencms.gwt.client.ui.input.upload.I_CmsUploadDialog::showErrorReport(Ljava/lang/String;Ljava/lang/String;)(xhr.statusText, null);
109                        }
110                    }
111                }
112                xhr.sendAsBinary(body);
113            }
114        }
115
116        // appends the infos to the request body
117        // should be called at end of creating the body because the boundary is closed here
118        function appendInfos() {
119            addPlainField(body, @org.opencms.gwt.shared.I_CmsUploadConstants::KEEP_FILE_NAMES, ""+keepFileNames);
120            for (var i = 0; i < filesToUnzip.length; ++i) {
121                var filename = filesToUnzip[i];
122                addPlainField(
123                        body,
124                        @org.opencms.gwt.shared.I_CmsUploadConstants::UPLOAD_UNZIP_FILES_FIELD_NAME,
125                        encodeURI(filename));
126            }
127
128            addPlainField(
129                    body,
130                    @org.opencms.gwt.shared.I_CmsUploadConstants::UPLOAD_TARGET_FOLDER_FIELD_NAME,
131                    targetFolder);
132
133            addPlainField(
134                    body,
135                    @org.opencms.gwt.shared.I_CmsUploadConstants::POST_CREATE_HANDLER,
136                    postCreateHandler);
137
138            addPlainField(
139                    body,
140                    @org.opencms.gwt.shared.I_CmsUploadConstants::UPLOAD_IS_ROOT_PATH_FIELD_NAME,
141                    "" + isRootPath);
142        }
143
144        // the uri to call
145        var uri = uploadUri;
146        // the boundary
147        var boundary = "26924190726270";
148        // the request body with the starting boundary
149        var body = "--" + boundary + "\r\n";
150
151        // the main procedure
152        if (filesToUpload) {
153
154            var curIndex = 0;
155            var file = filesToUpload[curIndex];
156
157            var reader = new FileReader();
158            reader.onloadend = loaded;
159            reader.onerror = errorHandler;
160            // Read file into memory
161            reader.readAsBinaryString(file);
162        }
163    }-*/;
164
165    /**
166     * Switches the error message depending on the given error code.<p>
167     *
168     * The error codes are defined in the W3C file API.<p>
169     *
170     * <a href="http://www.w3.org/TR/FileAPI/#dfn-fileerror">http://www.w3.org/TR/FileAPI/#dfn-fileerror</a>
171     *
172     * @param dialog the upload dialog
173     * @param errorCode the error code as String
174     */
175    private void onBrowserError(I_CmsUploadDialog dialog, String errorCode) {
176
177        int code = Integer.valueOf(errorCode).intValue();
178        String errMsg = org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.ERR_UPLOAD_BROWSER_0);
179
180        switch (code) {
181            case 1: // NOT_FOUND_ERR
182                errMsg = org.opencms.gwt.client.Messages.get().key(
183                    org.opencms.gwt.client.Messages.ERR_UPLOAD_BROWSER_NOT_FOUND_0);
184                break;
185            case 2: // SECURITY_ERR
186                errMsg = org.opencms.gwt.client.Messages.get().key(
187                    org.opencms.gwt.client.Messages.ERR_UPLOAD_BROWSER_SECURITY_0);
188                break;
189            case 3: // ABORT_ERR
190                errMsg = org.opencms.gwt.client.Messages.get().key(
191                    org.opencms.gwt.client.Messages.ERR_UPLOAD_BROWSER_ABORT_ERR_0);
192                break;
193            case 4: // NOT_READABLE_ERR
194                errMsg = org.opencms.gwt.client.Messages.get().key(
195                    org.opencms.gwt.client.Messages.ERR_UPLOAD_BROWSER_NOT_READABLE_0);
196                break;
197            case 5: // ENCODING_ERR
198                errMsg = org.opencms.gwt.client.Messages.get().key(
199                    org.opencms.gwt.client.Messages.ERR_UPLOAD_BROWSER_ENCODING_0);
200                break;
201            default:
202                break;
203        }
204        dialog.showErrorReport(errMsg, null);
205    }
206}