JAVA实现的简易FTP站点
来源:互联网 发布:尼古拉斯赵四 知乎 编辑:程序博客网 时间:2024/06/05 16:04
在JAVA Socket的基础上增加了一些简单的功能,现在已经能够生成本地文件目录,提供文件下载了.
http://blog.csdn.net/coldcoding/article/details/53192607
在这个服务器的代码里增加了
目录生成部分,这些部分将在需要返回目录时起作用
public void doGet() throws IOException{ //资源地址 StringBuffer sb = new StringBuffer(root); sb.append(clientRequest.getRequestURI()); locaURI = sb.toString(); assert locaURI != null:"返回出错"; SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 System.out.print(df.format(new Date()) +" ");// new Date()为获取当前系统时间 System.out.println(locaURI); OutputStream out = responseSocket.getOutputStream(); //消息头 out.write("HTTP/1.0 200 OK\r\n".getBytes()); out.write("\r\n".getBytes()); // 根据 HTTP 协议, 空行将结束头信息 byte[] data = new byte[1024]; //缓冲区 int length = -1; out.flush(); if(locaURI.endsWith("/")){ //返回目录 InputStream input = new BufferedInputStream(new FileInputStream(this.root + "/GenerateIndex.html")); while((length = input.read(data)) != -1){ out.write(data, 0, length); out.flush(); } /*TODO根据目录构建索引*/ createDirect(this.locaURI,out); input.close(); out.close(); }else{ //返回文件 if(locaURI != null){ InputStream input = new BufferedInputStream(new FileInputStream(this.locaURI)); while((length = input.read(data)) != -1){ out.write(data, 0, length); out.flush(); } input.close(); out.close(); } } }public void createDirect(String path,OutputStream out) throws IOException{ //参数检查 //目录生成和写入 assert path != null:"生成目录出错"; File file = new File(path); if (file.exists()) { //头部 out.write(("</script><script>start(\"" + path + "\");</script>").getBytes()); out.write("<script>addRow(\"..\",\"..\",0,\"0 B\",\"\");</script>".getBytes()); out.flush(); File[] files = file.listFiles(); if (files.length == 0){ return; }else{ for (File file2 : files){ StringBuffer sb = new StringBuffer("\""); sb.append(file2.getName().replaceAll("\\/", "")); sb.append("\",\""); sb.append(file2.getName()); if(file2.isDirectory()) sb.append("\",1,\""); else sb.append("\",0,\""); sb.append(file2.getTotalSpace()); sb.append("\",\""); sb.append(file2.lastModified()); sb.append("\""); out.write("<script>addRow(".getBytes());//HTML的结尾添加addRow out.write(sb.toString().getBytes()); out.write(");</script>".getBytes()); out.flush(); } } } }
HTML文件会使用function addRow(name, url, isdir, size, date_modified)来生成要显示的内容,因此在返回HTML文件之后,在末尾写入需要的内容就行了
<!DOCTYPE html><html i18n-values="dir:textdirection;lang:language"><head><meta charset="utf-8"><meta name="google" value="notranslate"><script>function addRow(name, url, isdir, size, date_modified) { if (name == ".") return; var root = document.location.pathname; if (root.substr(-1) !== "/") root += "/"; var table = document.getElementById("table"); var row = document.createElement("tr"); var file_cell = document.createElement("td"); var link = document.createElement("a"); link.className = isdir ? "icon dir" : "icon file"; if (name == "..") { link.href = root + ".."; link.innerText = document.getElementById("parentDirText").innerText; link.className = "icon up"; size = ""; date_modified = ""; } else { if (isdir) { name = name + "/"; url = url + "/"; size = ""; } else { link.draggable = "true"; link.addEventListener("dragstart", onDragStart, false); } link.innerText = name; link.href = root + url; } file_cell.appendChild(link); row.appendChild(file_cell); row.appendChild(createCell(size)); row.appendChild(createCell(date_modified)); table.appendChild(row);}function onDragStart(e) { var el = e.srcElement; var name = el.innerText.replace(":", ""); var download_url_data = "application/octet-stream:" + name + ":" + el.href; e.dataTransfer.setData("DownloadURL", download_url_data); e.dataTransfer.effectAllowed = "copy";}function createCell(text) { var cell = document.createElement("td"); cell.setAttribute("class", "detailsColumn"); cell.innerText = text; return cell;}function start(location) { var header = document.getElementById("header"); header.innerText = header.innerText.replace("LOCATION", location); document.getElementById("title").innerText = header.innerText;}function onListingParsingError() { var box = document.getElementById("listingParsingErrorBox"); box.innerHTML = box.innerHTML.replace("LOCATION", encodeURI(document.location) + "?raw"); box.style.display = "block";}</script><style> h1 { border-bottom: 1px solid #c0c0c0; margin-bottom: 10px; padding-bottom: 10px; white-space: nowrap; } table { border-collapse: collapse; } tr.header { font-weight: bold; } td.detailsColumn { -webkit-padding-start: 2em; text-align: end; white-space: nowrap; } a.icon { -webkit-padding-start: 1.5em; text-decoration: none; } a.icon:hover { text-decoration: underline; } a.file { background : url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC ") left top no-repeat; } a.dir { background : url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") left top no-repeat; } a.up { background : url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat; } html[dir=rtl] a { background-position-x: right; } #listingParsingErrorBox { border: 1px solid black; background: #fae691; padding: 10px; display: none; }</style><title id="title"></title></head><body><div id="listingParsingErrorBox" i18n-values=".innerHTML:listingParsingErrorBoxText"></div><span id="parentDirText" style="display:none" i18n-content="parentDirText"></span><h1 id="header" i18n-content="header"></h1><table id="table"> <tr class="header"> <td i18n-content="headerName"></td> <td class="detailsColumn" i18n-content="headerSize"></td> <td class="detailsColumn" i18n-content="headerDateModified"></td> </tr></table></body></html><script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file./** * @fileoverview This file defines a singleton which provides access to all data * that is available as soon as the page's resources are loaded (before DOM * content has finished loading). This data includes both localized strings and * any data that is important to have ready from a very early stage (e.g. things * that must be displayed right away). */var loadTimeData;// Expose this type globally as a temporary work around until// https://github.com/google/closure-compiler/issues/544 is fixed./** @constructor */function LoadTimeData() {}(function() { 'use strict'; LoadTimeData.prototype = { /** * Sets the backing object. * * Note that there is no getter for |data_| to discourage abuse of the form: * * var value = loadTimeData.data()['key']; * * @param {Object} value The de-serialized page data. */ set data(value) { expect(!this.data_, 'Re-setting data.'); this.data_ = value; }, /** * Returns a JsEvalContext for |data_|. * @returns {JsEvalContext} */ createJsEvalContext: function() { return new JsEvalContext(this.data_); }, /** * @param {string} id An ID of a value that might exist. * @return {boolean} True if |id| is a key in the dictionary. */ valueExists: function(id) { return id in this.data_; }, /** * Fetches a value, expecting that it exists. * @param {string} id The key that identifies the desired value. * @return {*} The corresponding value. */ getValue: function(id) { expect(this.data_, 'No data. Did you remember to include strings.js?'); var value = this.data_[id]; expect(typeof value != 'undefined', 'Could not find value for ' + id); return value; }, /** * As above, but also makes sure that the value is a string. * @param {string} id The key that identifies the desired string. * @return {string} The corresponding string value. */ getString: function(id) { var value = this.getValue(id); expectIsType(id, value, 'string'); return /** @type {string} */ (value); }, /** * Returns a formatted localized string where $1 to $9 are replaced by the * second to the tenth argument. * @param {string} id The ID of the string we want. * @param {...string} var_args The extra values to include in the formatted * output. * @return {string} The formatted string. */ getStringF: function(id, var_args) { var value = this.getString(id); if (!value) return ''; var varArgs = arguments; return value.replace(/\$[$1-9]/g, function(m) { return m == '$$' ? '$' : varArgs[m[1]]; }); }, /** * As above, but also makes sure that the value is a boolean. * @param {string} id The key that identifies the desired boolean. * @return {boolean} The corresponding boolean value. */ getBoolean: function(id) { var value = this.getValue(id); expectIsType(id, value, 'boolean'); return /** @type {boolean} */ (value); }, /** * As above, but also makes sure that the value is an integer. * @param {string} id The key that identifies the desired number. * @return {number} The corresponding number value. */ getInteger: function(id) { var value = this.getValue(id); expectIsType(id, value, 'number'); expect(value == Math.floor(value), 'Number isn\'t integer: ' + value); return /** @type {number} */ (value); }, /** * Override values in loadTimeData with the values found in |replacements|. * @param {Object} replacements The dictionary object of keys to replace. */ overrideValues: function(replacements) { expect(typeof replacements == 'object', 'Replacements must be a dictionary object.'); for (var key in replacements) { this.data_[key] = replacements[key]; } } }; /** * Checks condition, displays error message if expectation fails. * @param {*} condition The condition to check for truthiness. * @param {string} message The message to display if the check fails. */ function expect(condition, message) { if (!condition) { console.error('Unexpected condition on ' + document.location.href + ': ' + message); } } /** * Checks that the given value has the given type. * @param {string} id The id of the value (only used for error message). * @param {*} value The value to check the type on. * @param {string} type The type we expect |value| to be. */ function expectIsType(id, value, type) { expect(typeof value == type, '[' + value + '] (' + id + ') is not a ' + type); } expect(!loadTimeData, 'should only include this file once'); loadTimeData = new LoadTimeData;})();</script><script>loadTimeData.data = {"header":"LOCATION 的索引","headerDateModified":"修改日期","headerName":"名称","headerSize":"大小","listingParsingErrorBoxText":"糟糕!Google Chrome无法解读服务器所发送的数据。请\u003Ca href=\"http://code.google.com/p/chromium/issues/entry\">报告错误\u003C/a>,并附上\u003Ca href=\"LOCATION\">原始列表\u003C/a>。","parentDirText":"[上级目录]","textdirection":"ltr"};</script><script>// Copyright (c) 2012 The Chromium Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file.// // Copyright (c) 2012 The Chromium Authors. All rights reserved.// Use of this source code is governed by a BSD-style license that can be// found in the LICENSE file./** @typedef {Document|DocumentFragment|Element} */var ProcessingRoot;/** * @fileoverview This is a simple template engine inspired by JsTemplates * optimized for i18n. * * It currently supports three handlers: * * * i18n-content which sets the textContent of the element. * * <span i18n-content="myContent"></span> * * * i18n-options which generates <option> elements for a <select>. * * <select i18n-options="myOptionList"></select> * * * i18n-values is a list of attribute-value or property-value pairs. * Properties are prefixed with a '.' and can contain nested properties. * * <span i18n-values="title:myTitle;.style.fontSize:fontSize"></span> * * This file is a copy of i18n_template.js, with minor tweaks to support using * load_time_data.js. It should replace i18n_template.js eventually. */var i18nTemplate = (function() { /** * This provides the handlers for the templating engine. The key is used as * the attribute name and the value is the function that gets called for every * single node that has this attribute. * @type {!Object} */ var handlers = { /** * This handler sets the textContent of the element. * @param {!HTMLElement} element The node to modify. * @param {string} key The name of the value in |data|. * @param {!LoadTimeData} data The data source to draw from. * @param {!Array<ProcessingRoot>} visited */ 'i18n-content': function(element, key, data, visited) { element.textContent = data.getString(key); }, /** * This handler adds options to a <select> element. * @param {!HTMLElement} select The node to modify. * @param {string} key The name of the value in |data|. It should * identify an array of values to initialize an <option>. Each value, * if a pair, represents [content, value]. Otherwise, it should be a * content string with no value. * @param {!LoadTimeData} data The data source to draw from. * @param {!Array<ProcessingRoot>} visited */ 'i18n-options': function(select, key, data, visited) { var options = data.getValue(key); options.forEach(function(optionData) { var option = typeof optionData == 'string' ? new Option(optionData) : new Option(optionData[1], optionData[0]); select.appendChild(option); }); }, /** * This is used to set HTML attributes and DOM properties. The syntax is: * attributename:key; * .domProperty:key; * .nested.dom.property:key * @param {!HTMLElement} element The node to modify. * @param {string} attributeAndKeys The path of the attribute to modify * followed by a colon, and the name of the value in |data|. * Multiple attribute/key pairs may be separated by semicolons. * @param {!LoadTimeData} data The data source to draw from. * @param {!Array<ProcessingRoot>} visited */ 'i18n-values': function(element, attributeAndKeys, data, visited) { var parts = attributeAndKeys.replace(/\s/g, '').split(/;/); parts.forEach(function(part) { if (!part) return; var attributeAndKeyPair = part.match(/^([^:]+):(.+)$/); if (!attributeAndKeyPair) throw new Error('malformed i18n-values: ' + attributeAndKeys); var propName = attributeAndKeyPair[1]; var propExpr = attributeAndKeyPair[2]; var value = data.getValue(propExpr); // Allow a property of the form '.foo.bar' to assign a value into // element.foo.bar. if (propName[0] == '.') { var path = propName.slice(1).split('.'); var targetObject = element; while (targetObject && path.length > 1) { targetObject = targetObject[path.shift()]; } if (targetObject) { targetObject[path] = value; // In case we set innerHTML (ignoring others) we need to recursively // check the content. if (path == 'innerHTML') { for (var i = 0; i < element.children.length; ++i) { processWithoutCycles(element.children[i], data, visited, false); } } } } else { element.setAttribute(propName, /** @type {string} */(value)); } }); } }; var prefixes = ['']; // Only look through shadow DOM when it's supported. As of April 2015, iOS // Chrome doesn't support shadow DOM. if (Element.prototype.createShadowRoot) prefixes.push('* /deep/ '); var attributeNames = Object.keys(handlers); var selector = prefixes.map(function(prefix) { return prefix + '[' + attributeNames.join('], ' + prefix + '[') + ']'; }).join(', '); /** * Processes a DOM tree using a |data| source to populate template values. * @param {!ProcessingRoot} root The root of the DOM tree to process. * @param {!LoadTimeData} data The data to draw from. */ function process(root, data) { processWithoutCycles(root, data, [], true); } /** * Internal process() method that stops cycles while processing. * @param {!ProcessingRoot} root * @param {!LoadTimeData} data * @param {!Array<ProcessingRoot>} visited Already visited roots. * @param {boolean} mark Whether nodes should be marked processed. */ function processWithoutCycles(root, data, visited, mark) { if (visited.indexOf(root) >= 0) { // Found a cycle. Stop it. return; } // Mark the node as visited before recursing. visited.push(root); var importLinks = root.querySelectorAll('link[rel=import]'); for (var i = 0; i < importLinks.length; ++i) { var importLink = /** @type {!HTMLLinkElement} */(importLinks[i]); if (!importLink.import) { // Happens when a <link rel=import> is inside a <template>. // TODO(dbeam): should we log an error if we detect that here? continue; } processWithoutCycles(importLink.import, data, visited, mark); } var templates = root.querySelectorAll('template'); for (var i = 0; i < templates.length; ++i) { var template = /** @type {HTMLTemplateElement} */(templates[i]); if (!template.content) continue; processWithoutCycles(template.content, data, visited, mark); } var isElement = root instanceof Element; if (isElement && root.webkitMatchesSelector(selector)) processElement(/** @type {!Element} */(root), data, visited); var elements = root.querySelectorAll(selector); for (var i = 0; i < elements.length; ++i) { processElement(elements[i], data, visited); } if (mark) { var processed = isElement ? [root] : root.children; if (processed) { for (var i = 0; i < processed.length; ++i) { processed[i].setAttribute('i18n-processed', ''); } } } } /** * Run through various [i18n-*] attributes and populate. * @param {!Element} element * @param {!LoadTimeData} data * @param {!Array<ProcessingRoot>} visited */ function processElement(element, data, visited) { for (var i = 0; i < attributeNames.length; i++) { var name = attributeNames[i]; var attribute = element.getAttribute(name); if (attribute != null) handlers[name](element, attribute, data, visited); } } return { process: process };}());i18nTemplate.process(document, loadTimeData);</script>
1 0
- JAVA实现的简易FTP站点
- Java语言实现简单FTP软件------>辅助功能模块FTP站点管理的实现(十二)
- java访问站点 并实现简易网络爬虫
- ftp站点的建立
- Java 实现的简易浏览器
- 常见的FTP站点资源
- 又一个不错的ftp站点
- DreamWeaver 的FTP站点配置
- java实现ftp的移动
- go语言实现简易ftp客户端
- java的简易科学计算器的实现
- 使用Java实现简易的HTTP服务器
- [JAVA]SAX实现的简易RSS阅读器
- Java实现一个简易的钟表
- JAVA实现简易的文件存储系统
- java实现的HTTP简易服务器
- JAVA简易贪吃蛇的实现
- Java回调的一种简易实现
- java写个纪念日
- 20 semaphore 2
- 【C语言学习笔记】初识GCC编译器
- HEVC MarginX MarginY的理解
- 内存快照排查OOM,加密时错误方法指定provider方式错误引起的OOM【原创】
- JAVA实现的简易FTP站点
- Codeforces Round #388 (Div. 2)E Inversions After Shuffle
- 批量备份/迁移SVN版本库
- 算法之路三:HDU OJ:2003
- 浅析聚合操作
- 第二十七节 Scala操纵XML
- PHP常用正则表达式
- android:baselineAligned=“false”
- PHP之HEADER隐藏文件下载路径