最近在做一个类似简单的云存储之类的东西,大概功能就是新建,删除文件夹,上传下载文件。笨鸟一只,在上传下载,以及功能对接时出现中文乱码,费了好大功夫。在同事帮助下顺利完成,记录一下大致的功能实现。
第一步:前台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;
}
大概就是这样了,以后如果有新的领悟,再继续写。。。