对象存储 文件上传功能

最近在做一个类似简单的云存储之类的东西,大概功能就是新建,删除文件夹,上传下载文件。笨鸟一只,在上传下载,以及功能对接时出现中文乱码,费了好大功夫。在同事帮助下顺利完成,记录一下大致的功能实现。

第一步:前台html,以及渲染所需css,也就是上传文件所需对话框部分:

<div id="DialogDiv"  class="modal-content modal hide" style="display:none">

	<h2 class="modal-header">文件上传<a href="#" id="btnClose" class="action" action="closeDiv">关闭</a></h2>
	<div class="modal-body">
	<div class="form" id = "fileupload_form">
	   <div class="controls">
		  <input id="fileupload" type="file" name="file" style="width:63px;border:1px solid #ccc;margin-left:5px;" >
       </div>
       <div class="controls">
		 <input name="file_name" id="file_name" type="text" style="width:302px;border:1px solid #ccc;margin-left:5px;" value="未导入任何文件" disabled=true/>
	   </div>
	   
    </div>
    </div>
    <div class="modal-footer">
        <button class="btn btn-default action" id="stratUpload" i18n="html:console.file.startUpload:开始上传"></button>
    </div>
</div>

渲染所需CSS如下:

#BgDiv {
	background-color: #fff;
	position: absolute;
	z-index: 99;
	left: 0;
	top: 0;
	display: none;
	width: 100%;
	height: 170px;
	opacity: 0.5;
	filter: alpha(opacity = 50);
	-moz-opacity: 0.5;
    }


#DialogDiv {
    background-color: #fff;
    border: 1px solid #8fa4f5;
    height: 170px;
    left: 35%;
    margin-left: -200px;
    padding: 1px;
    position: absolute;
    right: 50%;
    top: 50%;
    width: 600px;
    z-index: 100;
}

第二步:后台JS处理,这里主要是用到了JQuery的上传插件:fileupload

 "uploadFile" : function() {
    	debugger;
    	var self = this;
    	$("#BgDiv").css({
			display: "block",
			height: $(document).height()
		});
		var yscroll = document.documentElement.scrollTop;
		$("#DialogDiv").css("top", "100px");
		$("#DialogDiv").css("display", "block");
		document.documentElement.scrollTop = 0;
		var object = self._getSelectObjects()[0];
		var containerObj = this._getSelectedContainerName();
		var containerName = containerObj.text().trim();
	        var foldPath = self.foldPath;
	    
	        var url_fileUpload = System.getContextPath();
	        console.log("the url_fileUpload is " + url_fileUpload);
		$("#fileupload").fileupload({
			
			url :  url_fileUpload + "/callApi?api=/plugin/object/fileupload/uploadFile",
			dataType : "json",
			formData : {
				containerName : containerName,
				foldPath : foldPath,
			},
		
			add: function(e,data){
				var fileName = data.originalFiles[0].name;
				$("#file_name").val(fileName);
				$("#stratUpload").unbind("click").bind("click",function(){
	                    data.submit();
	                });
            },
			done : function(e, data) {
				debugger;
				console.log("上传文件成功~~~");
				System.notifyInfo($.i18nProp("console.notify.success:上传成功"));
				self._getFiles(containerObj);
				$("#DialogDiv").modal("hide");
				$("#fileupload_form").reset();   
			},
			beforeSend : function(xhr) {
				console.log("发送之前~~~");
			},
			progressall : function(e, data) {
				var progress = parseInt(data.loaded / data.total * 100, 10);
				$("#progress.bar").css("width", progress + "%");
			},
			fail : function(e,data){
				console.log("上传文件失败~~~");
		    }
		});
		
    	
    },
	


以上已经把需要上传的文件放在了data中,其他需要的参数 放在formdata中了。

第三步:在controller中接受JS传过去的数据。因为这个项目要求是调用底层的一个服务,所以我的指责就是把需要的文件流还有参数传过去就行。本来想着用JS直接传到底层服务,后来发现会出现跨域的错误。于是放弃,改作先在controller中接收数据,放在本地,再把相关需要的东西传过去。过程确实是有点啰嗦。

 @RequestMapping(value="/plugin/{type}/{fileupload}/{cmd}",method = RequestMethod.POST)
    @ResponseBody
    public Object executeFileUploadCmd(
    		@RequestParam MultipartFile file,
    		@PathVariable("type")String type,
    		@PathVariable("cmd")String cmd,
    		@PathVariable("fileupload")String fileupload,
    		HttpServletRequest request,
    		HttpServletResponse response
    		) {
    	 final String objectHost = ConfigurationUtil.load("config.properties").getProperty("object.host", "http://127.0.0.1:8080/");
    	 final  String URL_STR = objectHost + "/" + "uploadFile";  
    	System.out.println("文件长度: " + file.getSize());  
		System.out.println("文件类型: " + file.getContentType());
		System.out.println("文件名称: " + file.getName());  
		System.out.println("文件原名: " + file.getOriginalFilename()); 
		String fileName = "";
		try {
			fileName = new String(file.getOriginalFilename().getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}  

		
		PostMethod filePost = new PostMethod(URL_STR);
		String container = request.getParameter("containerName");
		try {
			container = new String(container.getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		String path = request.getParameter("foldPath");
		try {
			path = new String(path.getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		String dirTemp = "/obs/";
		ServiceCmdResponse result = new ServiceCmdResponse();
		try {
			InputStream  inputStream = file.getInputStream();
			FileOutputStream out = null;
	    	String userName = SecurityContext.getCurrentUser().getUsername();
	    	String password = SecurityContext.getCurrentUser().getUsername();
	        if ("".equals(path)){
	        	path = "/";
	        } else {}
			
			String tmpDirStr = dirTemp + userName + "/" + container + "/" + path;

			File tmpDir = new File(tmpDirStr);

			if (false == tmpDir.exists()) {
				tmpDir.mkdirs();
			}
			
			out = new FileOutputStream(tmpDir + "/" + fileName);
			byte[] buffer = new byte[4096];
			int len = -1;
			while ((len = inputStream.read(buffer)) != -1) {
				out.write(buffer, 0, len);
				out.flush();
			}
			out.close();
			inputStream.close();
			
	     HttpClient httpClient = new HttpClient();
	     
		File tmpFile = new File(tmpDir + "/" + fileName);
		System.out.println("fdgfxhgcjgggggggggg---- " + fileName);
		System.out.println("containercontainer---- " + container);
		System.out.println("pathpathpathpathpath---- " + path);
		Part[] parts = {new StringPart("userName", userName),new StringPart("password",password),new StringPart("containerName",URLEncoder.encode(container,"UTF-8")),new StringPart("foldPath",URLEncoder.encode(path,"UTF-8")),new FilePart(file.getName(),URLEncoder.encode(fileName,"UTF-8"), tmpFile) };
		
		filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
	    int statusCode = httpClient.executeMethod(filePost);
	    System.out.print("filePost.getResponseBodyAsString()="+filePost.getResponseBodyAsString());
	    System.out.println("statusCode is " + statusCode);  
	    if (statusCode == HttpStatus.SC_OK) {
		   return result;
	    } else {
		   return result;
	    }
			
          } catch (Exception e) {
			  e.printStackTrace();
			  return result;
		}
    	
    }

这里需要注意的重点一一介绍一下:

1:遇到的第一个问题就是中文文件名乱码的问题。这里主要处理如下:

String fileName = "";
		try {
			fileName = new String(file.getOriginalFilename().getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}  

fileName = new String(file.getOriginalFilename().getBytes("ISO-8859-1"), "UTF-8");

经过转码处理后,文件名即可显示成中文。其他参数亦可做相同处理。

2:如何把各个参数放在request中传递过去

之前试过setParam以及啥啥啥的,好像效果不怎么样。最后是百度的用MultipartRequestEntity来传递。主要代码如下:

Part[] parts = {new StringPart("userName", userName),new StringPart("password",password),new StringPart("containerName",URLEncoder.encode(container,"UTF-8")),new StringPart("foldPath",URLEncoder.encode(path,"UTF-8")),new FilePart(file.getName(),URLEncoder.encode(fileName,"UTF-8"), tmpFile) };
		
		filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
	    int statusCode = httpClient.executeMethod(filePost

);
第四步:接下来就该底层上场了。其实一般的上传时不用像这个例子似的传来传去的。因为我这个是必须要调一下这个服务,所以才写的有点啰嗦。实际开发时,可以把第四步的这个直接写在第三步里就行了。

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
	public ModelAndView uploadFile(HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		ModelAndView mv = new ModelAndView();

		InputStream inputStream = null;
		// 获得请求信息
		try {
			FileItemIterator fileItemIterator = null;
			ServletFileUpload upload = new ServletFileUpload();
			upload.setHeaderEncoding("utf-8");
			fileItemIterator = upload.getItemIterator(request);

			FileInfoBean fileUpload = null;
			long fileSize = -1l;
			String containerName = "";
			String foldPath = "";
			String fileName = "";
			String userName = null;
			String password = null;
			boolean hasAuth = false;
			long used = 0;
			while (fileItemIterator.hasNext()) {
				FileItemStream item = fileItemIterator.next();
				// auth for user
				if (userName != null && password != null && fileSize != -1l
						&& hasAuth == false) {
					UserInfo user = auth.authenticate(userName, password);// throw
																			// out
																			// if
																			// auth
																			// failed.
					hasAuth = true;
					// get user used space
					used = containerManage.getUsedSpace(userName);
					// check user's limited space
					if ((fileSize + used) > user.getAllocated()) {
						log.error(String
								.format("upload file failed, user[%s] have catched the limited space[%d].",
										userName, user.getAllocated()));
						mv.addObject("response", false);
						return mv;
					}
				}

				if (item != null && item.isFormField()) {
					BufferedReader reader = null;
					// 获取请求字段信息
					if (item.getFieldName() != null
							&& item.getFieldName().equals("fileSize")) {
						reader = new BufferedReader(new InputStreamReader(
								item.openStream()));
						fileSize = Long.valueOf(reader.readLine());
					}
					if (item.getFieldName() != null
							&& item.getFieldName().equals("containerName")) {
						reader = new BufferedReader(new InputStreamReader(
								item.openStream()));
						String temp_containerName = reader.readLine();
						containerName = URLDecoder.decode(temp_containerName,
								"utf-8");
					}
					if (item.getFieldName() != null
							&& item.getFieldName().equals("foldPath")) {
						reader = new BufferedReader(new InputStreamReader(
								item.openStream()));
						String temp_foldPath = reader.readLine();
						foldPath = URLDecoder.decode(temp_foldPath, "utf-8");
					}
					if (item.getFieldName() != null
							&& item.getFieldName().equals("userName")) {
						reader = new BufferedReader(new InputStreamReader(
								item.openStream()));
						String temp_username = reader.readLine();
						userName = (URLDecoder.decode(temp_username, "utf-8"));
					}
					if (item.getFieldName() != null
							&& item.getFieldName().equals("passWord")) {
						reader = new BufferedReader(new InputStreamReader(
								item.openStream()));
						String temp_password = reader.readLine();
						password = (URLDecoder.decode(temp_password, "utf-8"));
					}
				} else {
					// get input stream
					inputStream = item.openStream();
					fileName = item.getName();
					String str= new String(fileName.getBytes(),"UTF-8");
					str= (URLDecoder.decode(str, "utf-8"));
					 
					// upload file.
					fileUpload = this.iFileManage.uploadFile(userName,
							containerName, foldPath, str, inputStream);

				}
			}
			if (fileUpload != null) {
				String newFileName = fileUpload.getFileName();
				// get user used space
				used = containerManage.getUsedSpace(userName);
				// notify manager platform that user's space usage changed.
				iNotify.notifyUserUsage(userName, used);

				// log for user
				if (foldPath == null || foldPath.trim().equals("")) {
					oLog.log(userName, String.format(
							"在存储空间\"%s\"的根目录内上传了文件\"%s\".", containerName,
							newFileName));
				} else {
					oLog.log(userName, String.format(
							"在存储空间\"%s\"的目录\"%s\"内上传了文件\"%s\".", containerName,
							foldPath, newFileName));
				}

				log.info(String.format("user[%s] upload a file[%s].", userName,
						newFileName));
				mv.addObject("response", true);
				return mv;
			}

		} catch (Throwable e) {

			log.error(String.format("upload file failed."), e);

		} finally {
			if (inputStream != null)
				inputStream.close();
		}
		mv.addObject("response", false);
		return mv;
	}

这里需要注意的就是接收fileName时的处理。我原来在这里费了好大功夫,因为乱码的问题,在第三步中传过来的明明是中文,可到了这里,不是变成???,就是变成乱码,因为不知道这个底层到底是怎么设置的编码,所以试了好多次。最后,直接把它的编码方式变成我想要的了,然后乱码现象就消失了。主要代码就是下面这两句:

fileName = item.getName();
     String str= new String(fileName.getBytes(),"UTF-8");
     str= (URLDecoder.decode(str, "utf-8"));



@Override
	public FileInfoBean uploadFile(String userName, String container, String path,
			String fileName, InputStream inputStream) throws OperationException {

		FileOutputStream out = null;
		File file = null;
		File fileTo = null;
		FileInfoBean newFile = null;
		try {

			// fix me while more than two nfs
			String rootDir = ConfigLoader.getRootDirs().get(0);

			String userNameMD5 = MD5Util.MD5(userName);
			String containerPath = container + "/" + path;
			String fileStr = rootDir + "/" + userNameMD5 + "/" + containerPath
					+ "/" + fileName;
			System.out.println("fileStrfileStrfileStr================" + fileStr);  
			String tmpFileName = rootDir + "/" + userNameMD5 + "/"
					+ CommonValues.USER_TMP_DIR + "/" + fileName;
			System.out.println("tmpFileNametmpFileNametmpFileName================" + tmpFileName);  
			file = new File(tmpFileName);
			if (!file.exists()) {
				// create tmp dir
				String tmpDirStr = rootDir + "/" + userNameMD5 + "/"
						+ CommonValues.USER_TMP_DIR;
				File tmpDir = new File(tmpDirStr);
				System.out.println("tmpDir================" + tmpDir);  
				if (false == tmpDir.exists()) {
					System.out.println("tmpDir.exists()================" + tmpDir.exists());  
					tmpDir.mkdirs();
				}
				file.createNewFile();
			}

			out = new FileOutputStream(file);
			byte[] buffer = new byte[4096];

			int len = -1;
			while ((len = inputStream.read(buffer)) != -1) {
				out.write(buffer, 0, len);
				out.flush();
			}
			if (out != null) {
				out.close();
				out = null;
			}
			// move file
			String newFileStr = FileNameUtil.calculateFileName(fileStr);
			fileTo = new File(newFileStr);
			if (fileTo != null && fileTo.exists()) {
				fileTo.delete();
			}
			FileUtils.moveFile(file, fileTo);
//			FileUtils.copyFile(file, fileTo);
			// remove tmp file
			if (file != null && file.exists()) {
				file.delete();
			}
			newFile = toFileInfoBean(fileTo,container,userName);
			

		} catch (Exception ex) {
			// rm the file
			if (file != null && file.exists()) {
				try {
					if (out != null) {
						out.close();
						out = null;
					}
					file.delete();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
			if (fileTo != null && fileTo.exists()) {
//				fileTo.delete();
			}
			throw new OperationException("upload file failed!", ex);
		} finally {
			try {
				if (out != null) {

					out.close();

				}
				if (inputStream != null) {
					inputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
		return newFile;

	}

大概就是这样了,以后如果有新的领悟,再继续写。。。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值