前台
<div class="form-group"> <label class="col-sm-3 control-label">pc封面:</label> <div class="formControls col-sm-6"> <button type="button" class="btn btn-success radius" onclick="document.getElementById('coverForPc1').click();">选择文件</button> <span id="coverForPcName1" style="margin-left: 10px;"></span> <input type="file" id="coverForPc1" name="file" onchange="uploadBrandImageFile1();" class="form-file" style="display: none" /> <input type="hidden" id="coverForPc" name="coverForPc" value="" /> <img id="cover1" width="300px" height="100px" style="display: none"/> </div> </div>
js
function uploadBrandImageFile1() { // 第1个参数是type=file的ID,第2个参数是附件ID的hidden,第3个是附件名称的span uploadImage("coverForPc1", "coverForPc", "coverForPcName1", "cover1");
}
function uploadImage(inputFileId, inputHiddenId, inputNameId, imgId) { uploadFile("image", inputFileId, inputHiddenId, inputNameId, imgId, null); }
//Js
function openImagePreviewDiv(url, name) { $("#imagePreviewId").attr("src", url); var title = "图片预览"; if (name) { title = title + ":" + name; } layer.open({ type: 1, area: ['400px','290px'], fix: false, //不固定 maxmin: true, shade:0.4, title: title, content: $("#imagePreviewDiv").html() }); } function checkSessionLogin(userId, loginUrl) { if (window != top && userId == "") { top.location.href = loginUrl; } } /** * 附件下载 * * @param id * @returns */ function downloadAttachment(fileUrl) { if (id == null || id == "") { return; } window.location.href = basePath + "common/downloadFile.json?fileUrl=" + fileUrl; } /** * word上传 * * @param inputFileId * @param inputHiddenId * @param inputNameId * @param spanRowsId * @returns */ function uploadWord(inputFileId, inputHiddenId, inputNameId, spanRowsId) { uploadFile("word", inputFileId, inputHiddenId, inputNameId, null, null); } /** * excel上传 * * @param inputFileId * @param inputHiddenId * @param inputNameId * @param spanRowsId * @returns */ function uploadExcel(inputFileId, inputHiddenId, inputNameId, spanRowsId) { uploadFile("excel", inputFileId, inputHiddenId, inputNameId, null, spanRowsId); } /** * 图片上传 * * @param imgId * @param inputFileId * @param inputHiddenId * @param inputNameId * @returns */ function uploadImage(inputFileId, inputHiddenId, inputNameId, imgId) { uploadFile("image", inputFileId, inputHiddenId, inputNameId, imgId, null); } /** * 附件上传 * * @param inputFileId * @param inputHiddenId * @param inputNameId * @returns */ function uploadAttachment(inputFileId, inputHiddenId, inputNameId) { uploadFile("file", inputFileId, inputHiddenId, inputNameId, null, null); } /** * 文件上传,内部使用供其他方法重载 * * @param fileType * @param inputFileId * @param inputHiddenId * @param inputNameId * @param imgId * @param spanRowsId * @returns */ function uploadFile(fileType, inputFileId, inputHiddenId, inputNameId, imgId, spanRowsId) { var browser = getBrowserInfo(); if (browser == "IE0" || browser == "IE7" || browser == "IE8" || browser == "IE9" || browser == "IE10") { layer.alert("附件上传不支持该浏览器"); return; } var filePath = $("#" + inputFileId).val(); var fileName = filePath.substring(filePath.lastIndexOf("\\") + 1, filePath.length); var loading = $("<img src='" + basePath + "static/img/ajaxLoading.gif' id='fileLoading' />"); loading.css("position", "absolute").css("left", "50%").css("top", "45%").css("margin", "0 0 0 -32px").css("width", "64px").css("height", "64px").css("z-index", "99"); $("#" + inputFileId).parent().append(loading); if (inputNameId) $("#" + inputNameId).html(""); if (inputHiddenId) $("#" + inputHiddenId).val(""); if (imgId) $("#" + imgId).attr("src", ""); if (spanRowsId) $("#" + spanRowsId).html(""); $.ajaxFileUpload({ url : basePath + 'common/sysFile/uploadFile.json', // 用于文件上传的服务器端请求地址 secureuri : false, // 是否需要安全协议,一般设置为false fileElementId : inputFileId, // 文件上传域的ID dataType : 'json', // 返回值类型 一般设置为json data : {fileType : fileType}, success : function(data, textStatus) { console.log("fileUrl:"+data) console.log("fileUrl:"+data.fileUrl) $("#fileLoading").remove(); if (textStatus == "success") { if (data == false) { layer.alert("文件上传失败"); return; } if (data.errorCode == "-1") { layer.alert(data.errorMsg); return; } /*if (inputNameId) $("#" + inputNameId).html(fileName);*/ if (inputHiddenId) $("#" + inputHiddenId).val(data.fileUrl); if (imgId) $("#" + imgId).attr("src", data.fileUrl); $("#" + imgId).show(); if (spanRowsId) $("#" + spanRowsId).html(data.excelRows).parent().show(); } }, error : function(data, status, e) { console.log(data) alert(data.errorMsg); $("#fileLoading").remove(); if (inputNameId) $("#" + inputNameId).html(""); if (inputHiddenId) $("#" + inputHiddenId).val(""); if (imgId) $("#" + imgId).attr("src", ""); if (spanRowsId) $("#" + spanRowsId).html(""); } }); } /** * 获取浏览器信息(类型+版本) * * @returns */ function getBrowserInfo() { var userAgent = navigator.userAgent; // 取得浏览器的userAgent字符串 var isOpera = userAgent.indexOf("Opera") > -1; // 判断是否Opera浏览器 var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; // 判断是否IE浏览器 var isEdge = userAgent.indexOf("Windows NT 6.1; Trident/7.0;") > -1 && !isIE; // 判断是否IE的Edge浏览器 var isFF = userAgent.indexOf("Firefox") > -1; // 判断是否Firefox浏览器 var isSafari = userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") == -1; // 判断是否Safari浏览器 var isChrome = userAgent.indexOf("Chrome") > -1 && userAgent.indexOf("Safari") > -1; // 判断Chrome浏览器 if (isIE) { var reIE = new RegExp("MSIE (\\d+\\.\\d+);"); reIE.test(userAgent); var fIEVersion = parseFloat(RegExp["$1"]); if (fIEVersion == 7) { return "IE7"; } else if (fIEVersion == 8) { return "IE8"; } else if (fIEVersion == 9) { return "IE9"; } else if (fIEVersion == 10) { return "IE10"; } else if (fIEVersion == 11) { return "IE11"; } else { return "IE0" }// IE版本过低 } if (isFF) { return "Firefox"; } if (isOpera) { return "Opera"; } if (isSafari) { return "Safari"; } if (isChrome) { return "Chrome"; } if (isEdge) { return "Edge"; } } /** * 从url上获取id参数的值 * * @returns */ function getIdFromUrl() { // 获取ID var id = ""; var str = location.href; // 取得整个地址栏 var num = str.indexOf("?"); str = str.substr(num + 1); // 取得所有参数 stringvar.substr(start [, length ] var arr = str.split("&"); // 各个参数放到数组里 for (var i = 0; i < arr.length; i++) { num = arr[i].indexOf("="); if (num > 0) { name = arr[i].substring(0, num); value = arr[i].substr(num + 1); if (name == "id") { id = value; } } } return id; } function parseContent(content, max) { if (max == undefined) { max = 10; } if (content.length > max) { return '<span title="' + content + '">' + content.substring(0, max) + '...</span>'; } return content; }
后端
controller
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.servlet4preview.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import com.alibaba.fastjson.JSON; import com.ziku.ms.youle.common.BasicEnums.ErrorCode; import com.ziku.ms.youle.exception.BizException; import com.ziku.ms.youle.util.FTPClientUtil; import com.ziku.ms.youle.util.ProjectUtil; import com.ziku.ms.youle.util.ftpHelper.FtpClient; import com.ziku.ms.youle.util.ftpHelper.PropertyFtpConfig; import com.ziku.ms.youle.web.util.PageUtils; import lombok.extern.slf4j.Slf4j; @Slf4j @Controller @RequestMapping("/common/sysFile") @CrossOrigin public class FileController extends BaseController { @Autowired private FTPClientUtil ftpClientUtil; @Autowired private FtpClient ftpClient; @Autowired private PropertyFtpConfig propertyFtpConfig; @GetMapping("") String sysFile(Model model) { return "common/file/file"; } @ResponseBody @GetMapping("/list") public PageUtils list(@RequestParam Map<String, Object> params) { // 查询列表数据 PageUtils pageUtils = new PageUtils(null, 0); return pageUtils; } @RequestMapping(value = "uploadFile.json", method = RequestMethod.POST) public void uploadFile(HttpServletRequest req, HttpServletResponse resp, @RequestParam MultipartFile file, String fileType) throws Exception { Long fileSize = file.getSize(); if (file == null || file.getSize() == 0) { throw new BizException(StringUtils.EMPTY, "请选择文件!"); } String md5 = ProjectUtil.getFileMd5(file.getInputStream()); log.info("文件上传接口uploadFile,请求参数:file:{},filSize:{},md5:{}", file, fileSize, md5); String newFileName = FTPClientUtil.generateFileName(file.getOriginalFilename(), fileType); Map<String, Object> map = new HashMap<String, Object>(); Boolean flag = ftpClient.uploadFile(newFileName, file.getInputStream()); if (!flag) throw new BizException(ErrorCode.UPLOADFILEERROR); String fileUrl = ProjectUtil.appendUrl(propertyFtpConfig.getUrlPrefix(), newFileName); map.put("fileUrl", fileUrl); log.info("文件上传接口uploadFile,响应参数:fileUrl:{}", fileUrl); super.ajaxText(resp, JSON.toJSONString(map)); } @RequestMapping("downloadFile.json") public void downloadFile(HttpServletRequest req, HttpServletResponse resp, String fileUrl,String fileName) throws IOException { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { File file = new File(fileUrl); URL url = new URL(fileUrl); // 打开连接 URLConnection con = url.openConnection(); resp.setContentType("application/x-download"); String name = URLEncoder.encode(file.getName(), "UTF-8"); if(StringUtils.isNotBlank(fileName)) { name = fileName + ".jpg"; } // resp.addHeader("Content-Disposition", "attachment;filename=" + name); String headStr = "attachment; filename=\"" + new String(name.getBytes(), "iso-8859-1") + "\""; // resp.setContentType("APPLICATION/OCTET-STREAM"); resp.setHeader("Content-Disposition", headStr); bis = new BufferedInputStream(con.getInputStream()); bos = new BufferedOutputStream(resp.getOutputStream()); byte[] buff = new byte[2048]; int bytesRead; while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) { bos.write(buff, 0, bytesRead); } } catch (Exception e) { log.error(ProjectUtil.getErrorMessage(e), e); ProjectUtil.printStackTrace(e); super.ajaxError(resp, ProjectUtil.getErrorMessage(e)); } finally { if (bos != null) bos.close(); if (bis != null) bis.close(); } } }
上传工具类FTPClientUtil
import java.io.IOException; import java.io.InputStream; import org.apache.commons.lang3.StringUtils; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import com.ziku.ms.youle.common.BasicEnums.ErrorCode; import com.ziku.ms.youle.exception.BizException; import lombok.extern.slf4j.Slf4j; @Slf4j public class FTPClientUtil { private static final String fileTypeImage = "image"; private static final String fileTypeExcel = "excel"; private static final String fileTypeWord = "word"; private FTPClient ftpClient; private String remoteDirectory; private String host; private String userName; private String password; /** * 修改linux文件权限为777 * * @param filePath * @throws IOException */ private void setLinuxFileAuthority(String filePath) throws IOException { if (StringUtils.equalsIgnoreCase("linux", "linux")) { String cmd = "chmod 777 " + filePath; Runtime.getRuntime().exec(cmd); } } public void ftpClientInit() { try { if (ftpClient == null || ftpClient.isConnected() == false) { this.ftpClient = new FTPClient(); int ftpReply; ftpClient.connect(host);// 默认端口连接FTP服务器 ftpClient.login(userName, password); ftpReply = ftpClient.getReplyCode(); if (!FTPReply.isPositiveCompletion(ftpReply)) { ftpClient.disconnect(); log.info("ftp 连接失败!"); } log.info("ftp 连接成功!"); } } catch (IOException e) { e.printStackTrace(); log.error("ftp 连接异常 "); } } /** * 递归遍历出目录下面所有文件 * * @param pathName * 需要遍历的目录,必须以"/"开始和结束 * @throws IOException */ public void List(String pathName) throws IOException { if (pathName.startsWith("/") && pathName.endsWith("/")) { String directory = pathName; // 更换目录到当前目录 this.ftpClient.changeWorkingDirectory(directory); FTPFile[] files = this.ftpClient.listFiles(); for (FTPFile file : files) { if (file.isFile()) { log.info("list---fileName:" + file.getName()); } else if (file.isDirectory()) { List(directory + file.getName() + "/"); } } } } // ftp 上传文件 public String uploadFile(String newFileName, InputStream inputStream) { String url = ""; try { ftpClientInit(); ftpClient.setControlEncoding("UTF-8"); ftpClient.setBufferSize(1024); ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); ftpClient.changeWorkingDirectory(remoteDirectory); /// etc/httpd/htdocs/img.izhuan100.com/scrm/images ftpClient.storeFile(newFileName, inputStream); inputStream.close(); url = "http://" + remoteDirectory.replace("/etc/httpd/htdocs/", "") + newFileName; } catch (IOException e) { log.error("ftp 上传文件 异常 "); throw new BizException(ErrorCode.UPLOADFILEERROR); } finally { closeFTPConnect(); } return url; } public void closeFTPConnect() { try { ftpClient.logout(); if (this.ftpClient.isConnected()) { this.ftpClient.disconnect(); } } catch (IOException e) { e.printStackTrace(); log.error("ftp 关闭连接出现异常 ", e); } } // ftp 删除文件 public void delFile(String fileName) { try { ftpClientInit(); ftpClient.deleteFile(remoteDirectory + fileName); } catch (IOException e) { e.printStackTrace(); log.error("ftp 删除文件 异常 "); } } // ftp 下载文件 返回 InputStream public InputStream downloadFile(String fileName) { InputStream inputStream = null; try { ftpClientInit(); ftpClient.setBufferSize(1024); ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); inputStream = ftpClient.retrieveFileStream(remoteDirectory + fileName); } catch (IOException e) { e.printStackTrace(); log.error("ftp 下载文件 异常 "); } return inputStream; } public static String generateFileName(String fileName, String fileType) throws Exception { String newFileName = ""; if (StringUtils.isEmpty(fileName)) { throw new BizException(StringUtils.EMPTY, "请选择文件"); } if (StringUtils.equalsIgnoreCase(fileTypeImage, fileType)) { if (!StringUtils.endsWithIgnoreCase(fileName, ".jpg") && !StringUtils.endsWithIgnoreCase(fileName, ".png") && !StringUtils.endsWithIgnoreCase(fileName, ".gif")) { throw new BizException(StringUtils.EMPTY, "文件只支持jpg、png、gif格式"); } } if (StringUtils.equalsIgnoreCase(fileTypeExcel, fileType)) { if (!StringUtils.endsWithIgnoreCase(fileName, ".xlsx")) { throw new BizException(StringUtils.EMPTY, "文件只支持xlsx格式"); } } if (StringUtils.equalsIgnoreCase(fileTypeWord, fileType)) { if (!StringUtils.endsWithIgnoreCase(fileName, ".doc") && !StringUtils.endsWithIgnoreCase(fileName, ".docx")) { throw new BizException(StringUtils.EMPTY, "文件只支持doc、docx格式"); } } String type = fileName.indexOf(".") != -1 ? fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()) : null; newFileName = String.valueOf(System.currentTimeMillis()) + "-." + type; return newFileName; } public void setRemoteDirectory(String remoteDirectory) { this.remoteDirectory = remoteDirectory; } public void setHost(String host) { this.host = host; } public void setUserName(String userName) { this.userName = userName; } public void setPassword(String password) { this.password = password; } }
上传客户端import java.io.IOException; import java.io.InputStream; import java.util.Date; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.springframework.util.Assert; import com.ziku.ms.youle.util.DateUtil; /** * Ftp客户端 * * @author Xiongmw * @version 1.0.0 */ public class FtpClient { private FtpConfig ftpConfig; public FtpConfig getFtpConfig() { return ftpConfig; } public void setFtpConfig(FtpConfig ftpConfig) { this. ftpConfig = ftpConfig; } /** * 构建文件访问的Url * * @param url * @return */ public String buildFileUrl(String url) { Assert. notNull(getFtpConfig(), " param 'ftpConfig' can't be null!"); String urlPrefix = getFtpConfig().getUrlPrefix(); StringBuilder result = new StringBuilder(); result.append(urlPrefix); if (!urlPrefix.endsWith( "/") && !url.startsWith( "/")) result.append( "/"); result.append(url); return result.toString(); } /** * 创建文件路径 * * @param fileName * 原文件名称 * @param workDir * 放置目录 * @return */ public String buildFilePath(String fileName, String workDir) { StringBuilder fileNameBuilder = new StringBuilder(); fileNameBuilder.append(System. currentTimeMillis()); fileNameBuilder.append( "_"); fileNameBuilder.append(RandomStringUtils. random( 4, false, true)); fileNameBuilder.append( "."); fileNameBuilder.append(FilenameUtils. getExtension(fileName)); return buildFilePath(fileName, workDir, fileNameBuilder.toString()); } /** * 创建文件路径 * * @param fileName * 原文件名称 * @param workDir * 放置目录 * @param filename * 文件名称 * @return */ public String buildFilePath(String fileName, String workDir, String filename) { StringBuilder fileNameBuilder = new StringBuilder(); // String env = Config.env(); String env = "env"; // 根目录(当前所在环境目录) fileNameBuilder.append(env + "/"); // 自定义业务目录 fileNameBuilder.append(workDir + "/"); // 日期目录 fileNameBuilder.append(DateUtil. format( new Date(), "yyyyMMdd")); fileNameBuilder.append( "/"); // 文件名称 if (StringUtils. isBlank(filename)) { filename = System. currentTimeMillis() + "_"; filename += RandomStringUtils. random( 4, false, true); filename += "." + FilenameUtils. getExtension(fileName); } fileNameBuilder.append(filename); return fileNameBuilder.toString(); } /** * 创建ftp客户端 * * @return * @throws IOException */ protected FTPClient createFTPClient() throws IOException { Assert. notNull(getFtpConfig(), " param 'ftpConfig' can't be null!"); FtpConfig config = getFtpConfig(); FTPClient ftpClient = new FTPClient(); ftpClient.connect(config.getServer(), config.getPort()); boolean isSuccess = ftpClient.login(config.getUsername(), config.getPassword()); Assert. isTrue(isSuccess, "ftp login failure!"); ftpClient.enterLocalPassiveMode(); ftpClient.setBufferSize( 1024); // 设置上传缓存大小 ftpClient.setControlEncoding( "UTF-8"); // 设置编码 ftpClient.setFileType(FTP. BINARY_FILE_TYPE); // 设置文件类型 String path = config.getLocation(); if (StringUtils. isNotBlank(path) && !ftpClient.changeWorkingDirectory(path)) { Assert. isTrue(ftpClient.makeDirectory(path), "create dir '" + path + "' error!"); ftpClient.changeWorkingDirectory(path); } return ftpClient; } /** * 关闭ftp客户端 * * @param ftpClient * @throws IOException */ protected void closeFTPClient(FTPClient ftpClient) throws IOException { if (ftpClient != null && ftpClient.isConnected()) { ftpClient.logout(); ftpClient.disconnect(); } } /** * 级联创建目录 * * @param ftpClient * @param path * @return * @throws IOException */ public boolean createDir(FTPClient ftpClient, String path) throws IOException { if (StringUtils. isBlank(path)) return true; path = FilenameUtils. separatorsToUnix(path); String[] dirArrays = path.split( "/"); for (String dir : dirArrays) { if (ftpClient.changeWorkingDirectory(dir)) continue; Assert. isTrue(ftpClient.makeDirectory(dir), "create dir '" + dir + "' error!"); if (!ftpClient.changeWorkingDirectory(dir)) return false; } return true; } /** * 上传文件 * * @param fileName * @param iStream * @throws IOException */ public boolean uploadFile(String fileName, InputStream iStream) throws IOException { FTPClient ftpClient = null; try { ftpClient = createFTPClient(); String path = FilenameUtils. getPathNoEndSeparator(fileName); if (createDir(ftpClient, path)) { String name = FilenameUtils. getName(fileName); return ftpClient.storeFile(name, iStream); } else { throw new IOException( "change or make directory error!"); } } finally { closeFTPClient(ftpClient); IOUtils. closeQuietly(iStream); } }}
文件配置
/** * Ftp配置文件 * * @author xiongmw * @version 1.0.0 */ public interface FtpConfig { /** * 获取Hostname * * @return */ String getServer(); /** * 获取端口号 * * @return */ int getPort(); /** * 获取用户名 * * @return */ String getUsername(); /** * 获取密码 * * @return */ String getPassword(); /** * 获取存放路径 * * @return */ String getLocation(); /** * 获取访问的Url前缀 * * @return */ String getUrlPrefix(); }
读取文件配置
@Data @ToString @AllArgsConstructor @NoArgsConstructor public class PropertyFtpConfig implements FtpConfig { private String server; private int port; private String username; private String password; private String location; private String urlPrefix; }
ftp配置
ftpHost: ftpUserName: ftpPassword: ftpRemoteDirectory: ftpUrlPrefix: channelId: youleMemberRegisterUrl: