安卓app端上传文件到springMVC服务器端的问题

先上代码,上传文件的封装工具类如下:

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.UUID;


/**
 * Created by wishes on 2018/7/16.
 */

public class UploadUtil {


    public static final String TAG = UploadUtil.class.getName();

    private static final String CHARSET = "utf-8"; // 设置编码
    private static final int TIME_OUT = 8*1000;
    public static String result = null;
    /**
     * Android上传文件到服务端
     *
     * @param file 需要上传的文件
     * @param RequestURL 请求的rul
     * @return 返回响应的内容
     */
    public static String uploadFile(final File file, final String RequestURL) {

//        Thread thread = new Thread(new Runnable() {
//            @Override
//            public void run() {
                String result = null;
                String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
                String PREFIX = "--", LINE_END = "\r\n";
                String CONTENT_TYPE = "multipart/form-data"; // 内容类型
                try {
                    URL url = new URL(RequestURL);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();

                    conn.setReadTimeout(TIME_OUT);
                    conn.setConnectTimeout(TIME_OUT);
                    conn.setDoInput(true); // 允许输入流
                    conn.setDoOutput(true); // 允许输出流
                    conn.setUseCaches(false); // 不允许使用缓存
                    conn.setRequestMethod("POST"); // 请求方式
                    conn.setRequestProperty("Charset", CHARSET); // 设置编码
                    conn.setRequestProperty("connection", "keep-alive");
                    conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);


                    if (file != null) {
                        /**
                         * 当文件不为空,把文件包装并且上传
                         */
                        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
                        StringBuffer sb = new StringBuffer();
                        sb.append(PREFIX);
                        sb.append(BOUNDARY);
                        sb.append(LINE_END);
                        /**
                         * 这里重点注意: name里面的值为服务端需要key 只有这个key 才可以得到对应的文件
                         * filename是文件的名字,包含后缀名的 比如:abc.png
                         */

                        sb.append("Content-Disposition: form-data; name=\"upload\"; filename=\""
                                + file.getName() + "\"" + LINE_END);
                        sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END);
                        sb.append(LINE_END);
                        dos.write(sb.toString().getBytes());
                        InputStream is = new FileInputStream(file);
                        byte[] bytes = new byte[1024];
                        int len = 0;
                        while ((len = is.read(bytes)) != -1) {
                            dos.write(bytes, 0, len);
                        }
                        is.close();
                        dos.write(LINE_END.getBytes());
                        byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();
                        dos.write(end_data);
                        dos.flush();
                        /**
                         * 获取响应码 200=成功 当响应成功,获取响应的流
                         */
                        int res = conn.getResponseCode();
                        LOG.i(TAG, "response code:" + res);
                        if(res==200)
                        {
                        LOG.i(TAG, "request success");
                        InputStream input = conn.getInputStream();
                        StringBuffer sb1 = new StringBuffer();
                        int ss;
                        while ((ss = input.read()) != -1) {
                            sb1.append((char) ss);
                        }
                        result = sb1.toString();
                        UploadUtil.result = new String(result.getBytes("iso-8859-1"),"utf-8");
                        LOG.i(TAG, "result : " + UploadUtil.result);
                            input.close();
                        }
                        else{
                             LOG.e(TAG, "request error");
                        }

                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

//            }
//        });
//        thread.start();
        LOG.i(TAG, "---"+UploadUtil.result+"---");
        return  UploadUtil.result;
    }


    /**
     * 通过拼接的方式构造请求内容,实现参数传输以及文件传输
     *
     * @param url Service net address
     * @param params text content
     * @param files pictures
     * @return String result of Service response
     * @throws IOException
     */
    public static String post(String url, Map<String, String> params, Map<String, File> files)
            throws IOException {
        String BOUNDARY = java.util.UUID.randomUUID().toString();
        String PREFIX = "--", LINEND = "\r\n";
        String MULTIPART_FROM_DATA = "multipart/form-data";
        String CHARSET = "UTF-8";


        URL uri = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
        conn.setReadTimeout(10 * 1000); // 缓存的最长时间
        conn.setDoInput(true);// 允许输入
        conn.setDoOutput(true);// 允许输出
        conn.setUseCaches(false); // 不允许使用缓存
        conn.setRequestMethod("POST");
        conn.setRequestProperty("connection", "keep-alive");
        conn.setRequestProperty("Charsert", "UTF-8");
        conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);


        // 首先组拼文本类型的参数
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            sb.append(PREFIX);
            sb.append(BOUNDARY);
            sb.append(LINEND);
            sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
            sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
            sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
            sb.append(LINEND);
            sb.append(entry.getValue());
            sb.append(LINEND);
        }


        DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
        outStream.write(sb.toString().getBytes());
        // 发送文件数据
        if (files != null)
            for (Map.Entry<String, File> file : files.entrySet()) {
                StringBuilder sb1 = new StringBuilder();
                sb1.append(PREFIX);
                sb1.append(BOUNDARY);
                sb1.append(LINEND);
                sb1.append("Content-Disposition: form-data; name=\"upload\"; filename=\""
                        + file.getValue().getName() + "\"" + LINEND);
                sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);
                sb1.append(LINEND);
                outStream.write(sb1.toString().getBytes());


                InputStream is = new FileInputStream(file.getValue());
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = is.read(buffer)) != -1) {
                    outStream.write(buffer, 0, len);
                }


                is.close();
                outStream.write(LINEND.getBytes());
            }


        // 请求结束标志
        byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
        outStream.write(end_data);
        outStream.flush();
        // 得到响应码
        int res = conn.getResponseCode();
        InputStream in = conn.getInputStream();
        StringBuilder sb2 = new StringBuilder();
        if (res == 200) {
            int ch;
            while ((ch = in.read()) != -1) {
                sb2.append((char) ch);
            }
        }
        outStream.close();
        conn.disconnect();
        return sb2.toString();
    }

}

本次讨论的是第一个方法,即uploadFile方法。本人在最初使用这个方法上传图片时,把此方法体的大部分内容用一个线程(后来去掉了,上下边的代码注释掉)去执行网络请求操作(上传文件到服务器端),在获得请求结果时用本类中的一个静态变量result来接收并作为方法返回值返回。问题就在这里了,静态变量result在线程体内部被赋值了,在返回前却是null值,后来发现是线程的问题。即使是本类中的静态变量,在另一线程中被赋值了,在此线程结束后就被清空掉了。解决方案是,在此方法中去掉线程。在调用此方法处加入线程。代码如下:

  new Thread(){

                      @Override
                      public void run() {
                          //上传该图片到服务器
                          try {
                              File appDir = new File(Environment.getExternalStorageDirectory(), Constants.APP_LOCAL_STORE);
                              if (!appDir.exists()) {
                                  appDir.mkdir();
                              }

                              File file = new File(appDir, "/portrait.jpg");
                              LOG.i(TAG,file.getName());

                              String requestURL = Constants.HOME_URL+"/app/user/uploadFile.htm";

                              String result = UploadUtil.uploadFile(file,requestURL);


                              JSONObject json = new JSONObject(result);
                              JSONObject json1 = json.getJSONObject("result");
                              LOG.i(TAG,json1.getString("url"));

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

                      }
                  }.start();

以上代码是写在activity中的一个普通的方法。以上线程为子线程,可以在主线程中用Handle来处理,即监听子线程的状态后在Handle中做相应的处理。

例如,在子线程中调用sendEmptyMessage(int what)方法传入一个标识,然后在Handle的handleMessage方法中做相应处理。代码如下:

 //发送消息,通知UI组件显示图片
 handler.sendEmptyMessage(0x9527);
 private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if (msg.what==0x9527) {
                //显示从网上下载的图片
                imageview.setImageBitmap(bitmap);
            }
        }
    };

下面是服务器端代码:

//上传文件
	@RequestMapping(value="/app/user/uploadFile.htm",method = RequestMethod.POST)
	public String uploadFile(@RequestParam("upload") MultipartFile upload){
		
		logger.debug("uploadFile...");
		return execute(()->{
			if(!upload.isEmpty()){
									
				//上传文件路径
	            String uploadPath = request.getServletContext().getRealPath("").replace(Constants.PROJECT_NAME, Constants.UPLOAD)+File.separator+Constants.PROJECT_NAME;
	            //上传文件名
	            String uploadFileName = upload.getOriginalFilename();
	            String uploadFileType = uploadFileName.substring(uploadFileName.lastIndexOf("."),uploadFileName.length());
	            String filename = UUID.randomUUID().toString();
	            File file = new File(uploadPath , uploadFileName);
	            //判断路径是否存在,如果不存在就创建一个
	            if (!file.getParentFile().exists()) { 
	            	file.getParentFile().mkdirs();
	            }
	            upload.transferTo(new File(uploadPath + File.separator + filename+"."+uploadFileType));
	            
	            logger.debug("uploadPath:"+uploadPath);
	            
//	            FileUtils.copyFile(new File(uploadPath,filename), file);
	            
	            return ok(JsonResult.jsonResultSuccess("url",Constants.HOST+File.separator+Constants.UPLOAD+File.separator+Constants.PROJECT_NAME+File.separator+filename+uploadFileType));
			}else{
				return ok(JsonResult.jsonResultError("上传文件失败"));
			}
		});

成功则返回文件在服务器上的url;失败则提示。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring MVC中,可以使用MultipartResolver来处理文件。MultipartResolver是一个接口,Spring提供了两个实现类:CommonsMultipartResolver和StandardServletMultipartResolver。前者是通过Jakarta Commons FileUpload实现的,后者是通过Servlet 3.0的API实现的。这里以CommonsMultipartResolver为例介绍文件。 1. 在Spring配置文件中添加multipartResolver配置: ``` <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--设置上文件的最大值--> <property name="maxUploadSize" value="5242880"/> </bean> ``` 2. 在Controller中编写上文件的处理方法: ``` @RequestMapping(value = "/uploadFile", method = RequestMethod.POST) public String uploadFile(@RequestParam("file") MultipartFile file) { if (!file.isEmpty()) { try { //获取文件名 String fileName = file.getOriginalFilename(); //获取文件的字节数组 byte[] bytes = file.getBytes(); //将字节数组写入到文件中 String filePath = "/path/to/save/file/" + fileName; File outputFile = new File(filePath); OutputStream outputStream = new FileOutputStream(outputFile); outputStream.write(bytes); outputStream.close(); //将上文件的信息保存到数据库中 //... return "redirect:/success"; } catch (IOException e) { e.printStackTrace(); } } return "redirect:/error"; } ``` 在上面的方法中,@RequestParam("file")用于获取上文件,MultipartFile是Spring封装的文件对象,其中包含了上文件的相关信息,例如文件名、大小、内容等。通过调用getOriginalFilename()方法可以获取文件名,通过调用getBytes()方法可以获取文件的字节数组。接着,将字节数组写入到文件中,最后将上文件的相关信息保存到数据库中。 3. 将上文件存储到文件服务器上 如果需要将上文件存储到文件服务器上,可以使用FTPClient或SFTPClient等工具实现。具体实现方法可以参考FTPClient或SFTPClient的使用文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值