OkHttp上传文件及可能出现的问题

在开发过程中用的是http请求,但是响应流一直为空,获取到的响应流{"n_a_s":1,"atts":[]},最终修改用okhttp方法。http请求方法也放在文章最后,大家如果有类似的问题欢迎一起讨论。

    /**
     * OA附件生成接口
     * @param urlstr   上传地址
     * @param filename  路径
     * @param token
     * @return
     * @throws BusinessException
     * @throws IOException 
     */
    public static String filePost(String urlstr, String filename, String token) throws BusinessException, IOException {

        try {
        OkHttpClient client = new OkHttpClient().newBuilder().build();
                MediaType mediaType = MediaType.parse("text/plain");
                RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                  .addFormDataPart("file",filename,
                    RequestBody.create(MediaType.parse("application/octet-stream"),
                    new File(filename)))
                  .build();
                Request request = new Request.Builder()
                  .url("http://192.168.1.15:8090/seeyon/rest/attachment?token="+token)
                  .method("POST", body)
                  .addHeader("Cookie", "JSESSIONID=7144DE4003B79E88839BF28F5E89A171")
                  .build();
                Response response = client.newCall(request).execute();
                if (!response.isSuccessful())
                    throw new IOException("Unexpected code " + response);
                return response.body().string();
            } catch (IOException e) {
                throw new BusinessException(e.getMessage(), e);
            }
    }
public static String sendFiles(String urlstr, String filename,String token) throws BusinessException {
        
        DataOutputStream dos = null;
        OutputStream os = null;
        //生成一个文件,把文件转换成流对象FileBody
        File file = new File(filename);
        
        JSONObject json = new JSONObject();
        String BOUNDARY = "----WebKitFormBoundary7MA4YWxkTrZu0gW";
        //前缀
        String PREFIX = "--";
        //换行符
        String ROW = "\r\n";
        //产生一个边界
//        String BOUNDARY = UUID.randomUUID().toString().replaceAll("-" , "");

        try {
            URL url = new URL(urlstr.toString());
            //打开和url之间的连接
            HttpURLConnection hc = (HttpURLConnection) url.openConnection();
            //请求头
            //设置超时时间
            hc.setConnectTimeout(10000);
            //允许输入流
            hc.setDoInput(true);
            //允许输出流
            hc.setDoOutput(true);
            //不允许使用缓存
            hc.setUseCaches(false);
            //请求方式
            hc.setRequestMethod("POST");
            //设置通用的请求属性
            hc.setRequestProperty("accept", "*/*");
            //设置编码 utf-8
            hc.setRequestProperty("Charset", "utf-8");
            //设置为长连接
            hc.setRequestProperty("Connection", "Keep-Alive");
            //设置浏览器代理
            hc.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36");
            hc.setRequestProperty("token", token);
            //边界标识
//            String boundary = Long.toHexString(System.currentTimeMillis());
            
            //这里设置请求方式以及boundary的内容,即上面生成的随机字符串
//            hc.setRequestProperty("Content-Type", CONTENT_TYPE+"; boundary=----" + boundary);
            hc.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
            hc.connect();
            
            StringBuilder contentBody1 = new StringBuilder();
 
            DataOutputStream out =new DataOutputStream(hc.getOutputStream());
            
            os = hc.getOutputStream();
            dos = new DataOutputStream(os);
            
            String result = "";
            if (file != null) {
            //当文件不为空,把文件包装并且上传
            //这里定义输出流,用于之后向服务器发起请求
            
                //第一部分参数:excel文件
//                contentBody1.append("Content-Type:").append("multipart/form-data; boundary=" + BOUNDARY).append(ROW);
                contentBody1.append(ROW).append(BOUNDARY).append(ROW);
                //拼接文件名称
                contentBody1.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(file.getName())
                .append("\"")
                .append(ROW)
                //设置内容类型为流及编码为UTF-8
                .append("Content-Type: application/octet-stream; charset=UTF-8");
                //Todo 这两个换行很重要 标识文件信息的结束 后面的信息为文件流
                contentBody1.append(ROW).append(ROW);

                out.write(contentBody1.toString().getBytes(StandardCharsets.UTF_8));
            
              //写入文件流

                InputStreamReader reader=new InputStreamReader(new FileInputStream(file),"UTF-8");
                //读入缓冲区
                char[] buffer = new char[1024];
                //读入结果
                StringBuffer sb = new StringBuffer();
                //每次读入缓冲区的长度
                int len;
                //从读入流中读取文件内容并形成结果
                while ((len = reader.read(buffer)) != -1) {
                     sb.append(buffer, 0, len);
                }
                byte[] data = sb.toString().getBytes();
                // 向文件写入内容
                out.write(data);

                out.write(ROW.getBytes(StandardCharsets.UTF_8));
                
              //写入边界结束符
                out.write((BOUNDARY+PREFIX).getBytes(StandardCharsets.UTF_8));
                out.close();
                out.flush();//可以理解为发送请求
                
              //从服务器获得回答的内容
                /**
                 * 获取响应码 200=成功
                 * 当响应成功,获取响应的流
                 */
                int res = hc.getResponseCode();
                //获取后台返回的数据
                if (res == 200) {
                    BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(hc.getInputStream()));
                    String line;
                    StringBuffer sb_result = new StringBuffer();
                    while ((line = bufferedReader.readLine()) != null) {
                        sb_result.append(line);
                    }
                    return sb_result.toString();
//                    out.close(); 
         }else {
                BufferedReader bReader = new BufferedReader(new InputStreamReader(hc.getErrorStream(), "UTF-8"));
                int ch;
                while ((ch = bReader.read()) != -1) {
                    result += String.valueOf((char) ch);
                }
                throw new BusinessException(result, res + "");
            }    }    
        } catch (Exception e) {
            Logger.error("发送 POST 请求出现异常!" + e);
            throw new BusinessException("发送 POST 请求出现异常:" + e.getMessage(), e);
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (Exception e2) {
                    Logger.error(e2.getMessage(), e2);
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (Exception e2) {
                    Logger.error(e2.getMessage(), e2);
                }
            }
            if(!"".equals(json)&&json!=null) {
                JSONObject parseObject = JSONObject.parseObject(json.toString());
                Object object = parseObject.get("fileUrl");
                if(!"".equals(object)&&object!=null) {
                    return object.toString();
                }
//                log.writesendlog(url1+";;type:"+type+";;;数据:"+param, entityName+"error","");
            }
        }
        return FAILURE;
    }

PS:okhttp方法需要okhttp3和okio两个jar包,需要可以私信。


今天代码打到测试环境发现上传附件还是获取不到fileurl这个值,在postman测试时发送正常,我将postman中的代码取出(如下),怀疑是Cookie引发的问题,仔细查看Cookie获取的是JSESSIONID,这个id是从哪里获取到的呢?

OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                  .addFormDataPart("file","/C:/Users/86177/Desktop/发起OA流程表单接口.doc",
                  RequestBody.create(MediaType.parse("application/octet-stream"),
                  new File("/C:/Users/86177/Desktop/发起OA流程表单接口.doc")))
                  .build();
Request request = new Request.Builder()
                  .url("https://127.0.0.1:80/seeyon/rest/attachment?token=391ed45d-798a-4a08-b0cd-6631ac2173b6")
                  .method("POST", body)
                  .addHeader("Cookie", "JSESSIONID=FC05529B631B89C2F1B9F21DDC845A50; route=d9b669d27408c3f4e55a50b632da8fb2")
                  .build();
Response response = client.newCall(request).execute();

让我们先看一下用postman获取到的附件上传的截图,图中可以看出此时可以附件已经发送成功,Cookie的值是187EC412AF0F028ACFA24BDB59FEF602,我询问了OA的老师,老师说token要获取登录名,建议我看看有没有获取到,我才想起来之前发送HTTP请求是我并没有绑定登录名,我用postman再次查看之前获取token的信息。

OkHttp上传文件及可能出现的问题_第1张图片

此时可以看到绑定登录者的token返回时会带回sessionid,这个值就是我们想要的,请求的url地址应该是http://IP:端口/seeyon/rest/token/用户名/密码?loginName=登录名

OkHttp上传文件及可能出现的问题_第2张图片

在HTTP请求获取token返回时还遇到了中文乱码问题,一并指出,在下文得到输入流时进行utf-8转码,最后从result结果中获取到发送成功的id,不需要sessionid,因为绑定了用户名的id可以在发送附件时自动存储在cookie。以上就是我在开发中遇到的问题,希望对你有所帮助。

    /**
     * 获取token
     * @return
     */
    public static String getToken2() {
        String result = "";
        String id = "";
        
        try{
            String oAURL = SysInitQuery.getParaString("GLOBLE00000000000000", "OAURL");
            String oAusername = SysInitQuery.getParaString("GLOBLE00000000000000", "OAuser");
            String oAPassword = SysInitQuery.getParaString("GLOBLE00000000000000", "OApassword");
            StringBuilder lasturl = new StringBuilder(oAURL+"/seeyon/rest/token/"+oAusername+"/"+oAPassword+"?loginName=tianxiang");
            URL url = new URL(lasturl.toString());
            //打开和url之间的连接
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
            //请求头
            urlConn.setRequestProperty("Content-Type", "application/json");
            urlConn.setRequestProperty("Accept", "application/json;charset=UTF-8");
            
            urlConn.setDoOutput(true);
            urlConn.setDoInput(true);
            urlConn.setRequestMethod("GET");//GET和POST必须全大写
            urlConn.connect();

            int code = urlConn.getResponseCode();//获得响应码
            if(code == 200) {//响应成功,获得响应的数据
//                InputStream is = urlConn.getInputStream();//得到数据流(输入流)
                InputStreamReader is = new InputStreamReader(urlConn.getInputStream(),"UTF-8");
                BufferedReader bufferedReader = new BufferedReader(is);
                StringBuffer stringBuffer = new StringBuffer();
                String line = null;
                while ((line = bufferedReader.readLine()) != null) {
                    stringBuffer.append(line);
                }
                result = stringBuffer.toString();

                if(!"".equals(result)&&result!=null){
                    JSONObject parseObject = JSONObject.parseObject(result);
                    Object object = parseObject.get("id");
                    if(object != null && !"".equals(object)) {
                         urlConn.disconnect();   //断开连接
                        return object.toString();
                    }
                }
            }
            urlConn.disconnect();   //断开连接

        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

你可能感兴趣的:(用友,http,开发语言,后端)