后端开发--之文件上传
前言:
根据工程与学习的需要,最近接触了文件上传的相关知识,一开始由android端使用volley上传,遇到点问题,最后换成了OKhttp,服务器端采用spring MVC和flask,都成功了,将我的学习历程记录下来,为了更好的分享。
正文:
一、Spring MVC文件上传
在Intellij IDEA下开发,确实新的编辑器用起来方便许多,具体的安装我也是按照网上的教程来搭建环境的,搭建过程比较简单,以下是我搭建成功的教程:是个系列教程:
需要自己下载tomcat,我使用它系统的tomcat报错了,所以改为自己的tomcat,maven也需要自己配置,系统的也遇到了问题,搭建好后运行第一个web程序,测试完成。
下面开始文件上传的工作,首先需要在maven的pom.xml中引入要文件传输的包:
<!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <!-- https://mvnrepository.com/artifact/com.liferay/org.apache.commons.fileupload --> <dependency> <groupId>com.liferay</groupId> <artifactId>org.apache.commons.fileupload</artifactId> <version>1.2.2.LIFERAY-PATCHED-1</version> </dependency>
然后修改dispatcher里的加上支持文件的配置:
<!-- 支持上传文件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
我的dispatcher完整代码如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--指明 controller 所在包,并扫描其中的注解--> <context:component-scan base-package="com.controller"/> <!-- 静态资源(js、image等)的访问 --> <mvc:default-servlet-handler/> <!-- 开启注解 --> <mvc:annotation-driven/> <!--ViewResolver 视图解析器--> <!--用于支持Servlet、JSP视图解析--> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> </beans>
然后编写控制器代码,使用注解的方式指定url,请求方式,和报头的格式,具体的代码如下:
/** * Created by Y-GH on 2017/4/5. */ // 注解标注此类为springmvc的controller,url映射为"/home" @Controller @RequestMapping("/home") public class HomeController { //添加一个日志器 private static final Logger logger = LoggerFactory.getLogger(HomeController.class); //映射一个action @RequestMapping(value="/upload",method=RequestMethod.POST,headers = "Accept=application/octet-stream") public String upload(HttpServletRequest request, HttpServletResponse response, @RequestParam("file") MultipartFile file) throws Exception{ //输出日志文件 System.out.println("upload begin"); logger.info("the first jsp pages"); JSONObject object = new JSONObject(); //返回一个index.jsp这个视图 //如果文件不为空,写入上传路径 if(!file.isEmpty()) { //上传文件路径 System.out.println("开始"); String path = request.getSession().getServletContext().getRealPath("upload"); // String path = request.getSession().getServletContext().getRealPath("/images/"); //上传文件名 String filename = file.getOriginalFilename(); File filepath = new File(path,filename); //判断路径是否存在,如果不存在就创建一个 if (!filepath.getParentFile().exists()) { filepath.getParentFile().mkdirs(); } //将上传文件保存到一个目标文件当中 file.transferTo(new File(path + File.separator + filename)); object.put("results", "success"); return "success"; } else { object.put("results", "error"); return "error"; } } }
使用MultipartFile上传文件,很轻松就实现了,android端的代码最后贴。
二、使用flask上传文件
flask上传文件只需要几行代码,更加方便,代码如下:
import json from flask import Flask from flask import request from flask import redirect from flask import jsonify app = Flask(__name__) @app.route('/upload', methods=['GET', 'POST']) def upload_file(): if request.method == 'POST': f = request.files['file'] f.save('/home/ygh/flask/img_card.jpg') data = '{"result":"sucess"}' result = json.loads(data) return json.dumps(result) else: return "error" if __name__ == '__main__': app.run(host='0.0.0.0')
指定url后,判断是否是post请求,是post请求只需要将request的文件取出即可,然后使用save保存到指定的目录下,然后向客户端返回json格式的结果。
这里的文件请求都没有使用数据库,使用数据库只需要将文件名和路径存入数据表中,下次取地址后,直接遍历取出文件即可。
-------------------------------------------------------------------------------------------------
接下来我把android客户端的OKhttp下的请求代码也贴出来,方便参考:
首先引入Okhttp的依赖:
compile 'com.squareup.okhttp:okhttp:2.4.0' compile 'com.squareup.okio:okio:1.5.0'
然后在java中实现即可,还没有来得及进行封装,用的原生的方式:
//首先在主线程的onCreate或onActivityResult开启线程: new Thread(this).start(); //然后重写系统回掉方法, //注意 MainActivity extends AppCompatActivity implements Runnable @Override public void run() { try { PostFile(imgPath); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } //上传方法 集成了okhttp private void PostFile(String imgPath) throws IOException, JSONException { File file = new File(imgPath); if (!file.exists()) { Toast.makeText(MainActivity.this, "文件不存在,请修改文件路径", Toast.LENGTH_SHORT).show(); return; } //开始找到路径放入请求体内 RequestBody body = new MultipartBuilder() .addFormDataPart("file",imgPath , RequestBody.create(MediaType.parse("media/type"), new File(imgPath))) .type(MultipartBuilder.FORM) .build(); //建立请求 Request request = new Request.Builder() .url(url) .post(body) .build(); OkHttpClient client = new OkHttpClient(); Response response = client.newCall(request).execute();//发送请求 String tempResponse = response.body().string(); Log.e("==返回結果==","---"+tempResponse); JSONArray arr = new JSONArray(tempResponse); String responsew = arr.getString(0); JSONObject obj = new JSONObject(responsew); result = obj.getString("result"); Log.e("==输出==","--"+result); if(result.equals("sucess")){ JSONObject obj2 = new JSONObject(obj.getString("response")); Log.e("==response==","------"+obj.getString("response")); String day = obj2.getString("day"); Log.e("---day---","==>"+day); mHandler.sendEmptyMessage(0); }else if(result.equals("error")){ Log.e("==返回==","---出错---"); mHandler.sendEmptyMessage(1); } } //根据返回结果执行mHandler相应传入处理消息的方式 private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0: dialog.cancel(); Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show(); break; case 1: dialog.cancel(); Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show(); break; } }; };
至此,完成了文件上传的基本功能,后续有新的方法会及时补充。
by STILL