在很多项目中都会有一台专门的文件服务器来保存文件的,这边记录下客户端通过jersey上传图片到文件服务端的实现。

由于要在不同主机上上传文件,所以不能直接通过流的方式来写,需要通过webService来完成,jersey是基于Java的一个轻量级RESTful风格的Web Services框架,它让客户端文件上传变得更简单。

1. maven依赖

spring的一些包以及fileupload和io包这边就不贴出来了。




<          dependency          >         


                    <          groupId          >com.sun.jersey</          groupId          >         


                    <          artifactId          >jersey-client</          artifactId          >         


                    <          version          >1.2</          version          >         


          </          dependency          >



2. 配置tomcat下的conf/web.xml文件

打开文件服务器下的此文件,然后搜索readonly这个单词,可以看到这段注释代码:




<!--  readonly      Is this context "read only", so HTTP    -->         


          <!--            commands like PUT and DELETE are      -->         


          <!--            rejected? [true]             -->



通过注释可以看到默认情况下当我们进行put或者delete操作的时候,服务器是拒绝访问的,所以想向服务器上传文件必须将readonly属性设置为false。



<          servlet          >         


                    <          servlet-name          >default</          servlet-name          >         


                    <          servlet-class          >org.apache.catalina.servlets.DefaultServlet</          servlet-class          >         


                    <!-- 添加,解决jersey上传服务器403错误 -->         


                    <          init-param          >         


                    <          param-name          >readonly</          param-name          >         


                    <          param-value          >false</          param-value          >         


                    </          init-param          >         


                    <          init-param          >         


                    <          param-name          >debug</          param-name          >         


                    <          param-value          >0</          param-value          >         


                    </          init-param          >         


                    <          init-param          >         


                    <          param-name          >listings</          param-name          >         


                    <          param-value          >false</          param-value          >         


                    </          init-param          >         


                    <          load-on-startup          >1</          load-on-startup          >         


          </          servlet          >



3. 在文件服务器上创建文件存储目录


java src连接下载图片到本地 java实现图片上传下载_上传文件

在webapp下创建一个upload目录,为了防止找不到目录,在空目录下随便添加一个文件。

4. controller代码




@Controller         


          @RequestMapping          (          "/upload"          )         


          public           class           UploadController           extends           BaseController {         


                    @RequestMapping          (value =           "/uploadPic"          , method = RequestMethod.POST)         


                    @LoginCheck         


                    public           void           uploadPic(HttpServletRequest request, PrintWriter out, String lastRealPath)           throws           IOException {         


                    // 将当前上下文初始化给CommonsMultipartResolver         


                    CommonsMultipartResolver resolver =           new           CommonsMultipartResolver(request.getSession().getServletContext());         


                    // 检查form中是否有enctype="multipart/form-data"         


                    if           (resolver.isMultipart(request)) {         


                    // 强制转化request         


                    MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;         


                    // 从表单获取input名称         


                    Iterator<String> iterable = req.getFileNames();         


                    // 存在文件         


                    if           (iterable.hasNext()) {         


                    String inputName = iterable.next();         


                    // 获得文件         


                    MultipartFile mf = req.getFile(inputName);         


                    byte          [] mfs = mf.getBytes();         


                    // 定义文件名         


                    String fileName =           new           SimpleDateFormat(          "yyyyMMddHHmmssSSS"          ).format(          new           Date());         


                    Random random =           new           Random();         


                    for           (          int           i =           0          ; i <           3          ; i++) {         


                    fileName = fileName + random.nextInt(          10          );         


                    }         


                    // 获得后缀名         


                    String oriFileName = mf.getOriginalFilename();         


                    String suffix = oriFileName.substring(oriFileName.lastIndexOf(          "."          ));         


                    


                    // 要上传文件的绝对路径         


                    String realPath = MallUtil.readProp(          "upload_file_path"          ) +           "/upload/"           + fileName + suffix;         


                    String relativePath =           "/upload/"           + fileName + suffix;         


                    


                    // 由于我们要在不同主机上上传文件,所以不能直接通过流的方式来写,需要通过webService来完成,这边借助Jersey来完成         


                    Client client = Client.create();         


                    


                    // 判断是不是第一次上传,如果已经上传过则删除上一次上传的文件         


                    if           (StringUtils.isNotBlank(lastRealPath)) {         


                    WebResource webService = client.resource(lastRealPath);         


                    webService.delete();         


                    }         


                    WebResource webService = client.resource(realPath);         


                    // 将文件传到主机上         


                    webService.put(mfs);         


                    // 将图片信息返回给界面回显         


                    Map<String, String> map =           new           HashMap<String, String>();         


                    map.put(          "realPath"          , realPath);         


                    map.put(          "relativePath"          , relativePath);         


                    // {"relativePath":"/upload/20170215135233634679.png","realPath":"http://localhost:8088/mall-file/upload/20170215135233634679.png"}         


                    out.write(JsonUtil.jsonString(map));         


                    }         


                    }         


                    }         


          }



5. 页面代码

需要回显就需要通过ajax来实现图片上传,这里使用的是jquery.form.js这个插件

jsp代码:



<form enctype=          "multipart/form-data"           id=          "form"          >            


          <div>         


                    ![](${path}/mall/image/load_image.png)         


                    <input type=          "file"           id=          "input-image"           name=          "input-image"           onchange=          "submitUpload()"          >         


                    <input id=          "input-relative-path"           name=          "imgs"           type=          "hidden"           >         


                    <input id=          "input-last-path"           type=          "hidden"          >         


                    </div>         


          </form>



js代码:




function           submitUpload() {         


                    var           option = {         


                    url: path +           "/upload/uploadPic.do"          ,         


                    type:           "post"          ,         


                    dataType:           "text"          ,           // 返回值的数据类型         


                    beforeSubmit:           function           (formData, jqForm, options) {         


                    var           imageValue = $(          "#input-image"          ).val();         


                    imageValue = $.trim(imageValue);         


                    return           (imageValue !=           ""          );           // 没有选择图片,则中断上传请求         


                    },         


                    success:           function           (responseText) {         


                    // {"relativePath":"/upload/20170215135233634679.png","realPath":"http://localhost:8088/mall-file/upload/20170215135233634679.png"}         


                    var           jsonObj = $.parseJSON(responseText);         


                    $(          "#image"          ).attr(          "src"          , jsonObj.realPath);         


                    $(          "#input-relative-path"          ).val(jsonObj.relativePath);         


                    $(          "#input-last-path"          ).val(jsonObj.realPath);         


                    },         


                    error:           function           () {         


                    alert(          "系统错误"          );         


                    }         


                    };          


                    $(          "#form"          ).ajaxSubmit(option);         


          }



6. 常见错误

403 则是conf/web.xml中没有添加readonly为false的配置

409 : com.sun.jersey.api.client.UniformInterfaceException:

PUT http://localhost:8888/mall-file/upload/20170115104302348740.jpg returned a response status of 409 Conflict

确保项目部署在8888端口下并启动成功,确保项目中存在upload目录。